123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448 |
- char *cknetv = "Network support, 9.0.297, 14 Jul 2011";
- /* C K C N E T -- Network support */
- /*
- Copyright (C) 1985, 2011,
- Trustees of Columbia University in the City of New York.
- All rights reserved. See the C-Kermit COPYING.TXT file or the
- copyright text in the ckcmai.c module for disclaimer and permissions.
- */
- /*
- REMINDER: Any changes made to this file that other modules depend must
- also be made to cklnet.c (for VOS) until such time as cklnet.c and this
- module are merged back together.
- NOTE TO CONTRIBUTORS: This file, and all the other shared (ckc and cku)
- C-Kermit source files, must be compatible with C preprocessors that support
- only #ifdef, #else, #endif, #define, and #undef. Please do not use #if,
- logical operators, or other preprocessor features in this module. Also,
- don't use any ANSI C constructs except within #ifdef CK_ANSIC..#endif.
- Authors:
- Frank da Cruz (fdc@columbia.edu),
- Columbia University Academic Information Systems, New York City.
- Jeffrey E Altman (jaltman@secure-endpoints.com) -- Primary
- maintainer/developer since about 1996.
- netopen() routine for TCP/IP originally by Ken Yap, Rochester University
- (ken@cs.rochester.edu) (no longer at that address).
- Missing pieces for Excelan sockets library from William Bader.
- Telnet protocol by Frank da Cruz and Jeffrey Altman.
- Rlogin protocol by Jeffrey E Altman.
- SSL support adapted by Jeffrey E Altman from work done by
- Tim Hudson <tjh@cryptosoft.com> +61 7 32781581
- TLS support by Jeffrey E Altman.
- HTTP support by Jeffrey E Altman.
- TGV MultiNet code by Frank da Cruz.
- MultiNet code adapted to WIN/TCP by Ray Hunter of TWG.
- MultiNet code adapted to DEC TCP/IP by Lee Tibbert of DEC and Frank da Cruz.
- TCP/IP support adapted to IBM TCP/IP 1.2.1,2.0 for OS/2 by Kai Uwe Rommel.
- CMU-OpenVMS/IP modifications by Mike O'Malley, Digital (DEC).
- X.25 support by Marcello Frutig, Catholic University,
- Rio de Janeiro, Brazil (frutig@rnp.impa.br) with fixes from
- Stefaan Eeckels, Eurokom, Luxembourg.
- David Lane added support for Stratus VOS X.25 1996.
- Stephen Riehm added support for IBM AIX X.25 in April 1998.
- Other contributions as indicated in the code.
- */
- #define CKCNET_C
- #include "ckcsym.h"
- #include "ckcdeb.h"
- #include "ckcker.h"
- #include "ckcasc.h"
- #ifdef I386IX /* Has to come before ckcnet.h in */
- #include <errno.h> /* this version, but after in others */
- #endif /* I386IX */
- #include "ckcnet.h" /* which includes ckctel.h */
- #ifdef CK_SSL
- #include "ck_ssl.h"
- #endif /* CK_SSL */
- #ifdef CK_DNS_SRV
- #ifdef OS2
- #ifdef NT
- #include <wshelper.h>
- #else /* NT */
- /* !Error OS/2 does not support DNS Service Records. */
- #endif /* NT */
- #else /* OS2 */
- #include <arpa/inet.h>
- #ifdef USE_NAMESER_COMPAT
- #include <arpa/nameser_compat.h>
- #endif /* USE_NAMESER_COMPAT */
- #ifdef MINIX3
- #include <net/gen/resolv.h>
- #include <net/gen/nameser.h>
- #else
- #include <arpa/nameser.h>
- #include <resolv.h>
- #endif /* MINIX 3 */
- #ifndef PS2AIX10
- #ifndef BSD4
- #ifndef I386IX
- #ifndef RTAIX
- #include <netdb.h>
- #endif /* RTAIX */
- #endif /* I386IX */
- #endif /* BSD4 */
- #endif /* PS2AIX10 */
- #endif /* OS2 */
- #ifndef T_SRV
- #define T_SRV 33
- #endif /* T_SRV */
- #ifndef T_TXT
- #define T_TXT 16
- #endif /* T_TXT */
- /* for old Unixes and friends ... */
- #ifndef MAXHOSTNAMELEN
- #define MAXHOSTNAMELEN 64
- #endif /* MAXHOSTNAMELEN */
- #define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1)
- #endif /* CK_DNS_SRV */
- #ifdef NONET
- #ifdef TCPIPLIB
- #undef TCPIPLIB
- #endif /* TCPIPLIB */
- #endif /* NONET */
- #ifndef NOMHHOST
- #ifdef datageneral
- #define NOMHHOST
- #else
- #ifdef HPUX5WINTCP
- #define NOMHHOST
- #endif /* HPUX5WINTCP */
- #endif /* datageneral */
- #endif /* NOMHHOST */
- #ifdef INADDRX
- struct in_addr inaddrx;
- #endif /* INADDRX */
- int ttnet = NET_NONE; /* Network type */
- int ttnproto = NP_DEFAULT; /* Network virtual terminal protocol */
- /* 0 = don't lowercase username for Rlogin/Telnet protocol */
- /* nonzero = do lowercase it. Add a SET command if necessary... */
- #ifdef VMS
- int ck_lcname = 1;
- #else
- int ck_lcname = 0;
- #endif /* VMS */
- extern int /* External variables */
- duplex, debses, seslog, sessft, wasclosed,
- ttyfd, quiet, msgflg, what, nettype, ttmdm;
- #ifdef IKSD
- extern int inserver;
- #endif /* IKSD */
- char myipaddr[20] = { '\0' }; /* Global copy of my IP address */
- char hostipaddr[64] = { '\0' }; /* Global copy of remote IP address */
- #ifdef NETCONN
- /* Don't need any of this if there is no network support. */
- #ifndef OS2
- /* Current fd-swapping hack is not thread-safe */
- #define HTTP_BUFFERING
- #endif /* OS2 */
- #ifdef HTTP_BUFFERING
- #define HTTP_INBUFLEN 8192
- static char http_inbuf[HTTP_INBUFLEN];
- static int http_bufp = 0, http_count;
- #endif /* HTTP_BUFFERING */
- /*
- NETLEBUF is (must be) defined for those platforms that call this
- module to do network i/o (e.g. netinc(), nettchk(), etc) rather
- than doing it themselves (ttinc(), ttchk(), etc). In this case
- the Telnet local-echo buffers and routines are defined and referenced
- here, rather than in the ck?tio.c module.
- */
- #ifdef NETLEBUF
- #define LEBUFSIZ 4096
- int ttpush = -1, le_data = 0; /* These are seen from outside */
- static CHAR le_buf[LEBUFSIZ]; /* These are used internally */
- static int le_start = 0, le_end = 0;
- int tt_push_inited = 0;
- #endif /* NETLEBUF */
- #ifdef CK_SOCKS /* SOCKS Internet relay package */
- #ifdef CK_SOCKS5 /* SOCKS 5 */
- #define accept SOCKSaccept
- #define bind SOCKSbind
- #define connect SOCKSconnect
- #define getsockname SOCKSgetsockname
- #define listen SOCKSlisten
- #else /* Not SOCKS 5 */
- #define accept Raccept
- #define bind Rbind
- #define connect Rconnect
- #define getsockname Rgetsockname
- #define listen Rlisten
- #endif /* CK_SOCKS5 */
- #endif /* CK_SOCKS */
- #ifdef DEC_TCPIP
- #include <time.h>
- #include <inet.h>
- #endif /* DEC_TCPIP */
- /* Also see ckcnet.h -- hmmm, why don't we always include inet.h? */
- #ifdef HPUX
- #ifndef HPUX7 /* HPUX 7.00 doesn't have it */
- #ifndef HPUX6 /* HPUX 6.00 doesn't have it */
- #include <arpa/inet.h> /* For inet_ntoa() prototype */
- #endif /* HPUX6 */
- #endif /* HPUX7 */
- #endif /* HPUX */
- #ifdef CMU_TCPIP
- #include <time.h>
- #endif /* CMU_TCPIP */
- #ifndef NODCLTIMEVAL
- #ifdef DCLTIMEVAL /* UnixWare 7 */
- struct timeval { /* And define these ourselves. */
- long tv_sec; /* (see comments in ckutio.c) */
- long tv_usec;
- };
- struct timezone {
- int tz_minuteswest;
- int tz_dsttime;
- };
- #endif /* DCLTIMEVAL */
- #endif /* NODCLTIMEVAL */
- #ifdef WINTCP
- #include <setjmp.h>
- #include <signal.h>
- #include <sys/time.h>
- /*
- The WIN/TCP code path is the same as that for MultiNet.
- Only the routine names have changed ...
- */
- #define socket_read netread
- #define socket_ioctl ioctl
- #define socket_write netwrite
- #define socket_close netclose
- #ifdef OLD_TWG /* some routines have evolved */
- extern int vmserrno, uerrno;
- #define socket_errno uerrno
- #define socket_perror perror /* which uses errno, not uerrno! */
- #else
- #define socket_errno errno
- #define socket_perror win$perror
- #endif /* OLD_TWG */
- #else /* Not WINTCP */
- #ifdef OSF13
- #ifdef CK_ANSIC
- #ifdef _NO_PROTO
- #undef _NO_PROTO
- #endif /* _NO_PROTO */
- #endif /* CK_ANSIC */
- #endif /* OSF13 */
- #ifndef I386IX
- #ifndef HPUXPRE65
- #include <errno.h> /* Error number symbols */
- #else
- #ifndef ERRNO_INCLUDED
- #include <errno.h> /* Error number symbols */
- #endif /* ERRNO_INCLUDED */
- #endif /* HPUXPRE65 */
- #endif /* I386IX */
- #include <signal.h> /* Everybody needs this */
- #ifdef ZILOG /* Zilog has different name for this */
- #include <setret.h>
- #else
- #include <setjmp.h>
- #endif /* ZILOG */
- #endif /* WINTCP */
- #ifdef datageneral /* Data General AOS/VS */
- #include <:usr:include:vs_tcp_errno.h>
- #include <:usr:include:sys:vs_tcp_types.h>
- #ifdef SELECT
- /*
- NOTE: This can be compiled and linked OK with SELECT defined
- but it doesn't work at all. Anybody who cares and knows how
- to fix it, feel free.
- */
- #include <:usr:include:sys:vs_tcp_time.h>
- #endif /* SELECT */
- #include <:usr:include:sys:socket.h>
- #include <:usr:include:netinet:in.h>
- #include <:usr:include:netdb.h>
- #endif /* datageneral */
- #ifndef socket_errno
- #define socket_errno errno
- #endif /* socket_errno */
- #ifdef TNCODE
- extern int tn_deb;
- #endif /* TNCODE */
- int tcp_rdns = /* Reverse DNS lookup */
- #ifdef DEC_TCPIP_OLD
- SET_OFF /* Doesn't seem to work in UCX */
- #else
- SET_AUTO
- #endif /* DEC_TCPIP */
- ;
- #ifdef CK_DNS_SRV
- int tcp_dns_srv = SET_OFF;
- #endif /* CK_DNS_SRV */
- _PROTOTYP( char * cmcvtdate, (char *, int) );
- #ifdef RLOGCODE
- _PROTOTYP( int rlog_ctrl, (CHAR *, int) );
- _PROTOTYP( static int rlog_oob, (CHAR *, int) );
- #ifndef TCPIPLIB
- _PROTOTYP( static SIGTYP rlogoobh, ( int ) );
- #endif /* TCPIPLIB */
- _PROTOTYP( static int rlog_ini, (CHAR *, int,
- struct sockaddr_in *,
- struct sockaddr_in *) );
- int rlog_mode = RL_COOKED;
- int rlog_stopped = 0;
- int rlog_inband = 0;
- #endif /* RLOGCODE */
- #ifndef NOICP
- extern int doconx; /* CONNECT-class command active */
- #endif /* NOICP */
- #ifdef IBMX25
- /* This variable should probably be generalised for true client/server
- * support - ie: the fd of the listening server, accepted calls should
- * be forked or at least handled via a second fd (for IBM's X.25 -
- * ttyfd always holds the active fd - ie the server becomes inactive
- * as long as a client is connected, and becomes active again when the
- * connection is closed)
- */
- int x25serverfd = 0; /* extern in ckcnet.h */
- int x25seqno = 0; /* Connection sequence number */
- int x25lastmsg = -1; /* A cheapskate's state table */
- #define X25_CLOSED 0 /* Default state: no connection, no STREAM */
- #define X25_SETUP 1 /* X.25 has been set up (no connection) */
- #define X25_CONNECTED 2 /* X.25 connection has been established */
- int x25_state = X25_CLOSED; /* Default state */
- #endif /* IBMX25 */
- #ifndef DEBUG
- #define deblog 0
- #endif /* DEBUG */
- #ifdef CK_NAWS /* Negotiate About Window Size */
- #ifdef RLOGCODE
- _PROTOTYP( int rlog_naws, (void) );
- #endif /* RLOGCODE */
- #endif /* CK_NAWS */
- #ifdef OS2 /* For terminal type name string */
- #include "ckuusr.h"
- #ifndef NT
- #include <os2.h>
- #undef COMMENT
- #endif /* NT */
- #include "ckocon.h"
- extern int tt_type, max_tt;
- extern struct tt_info_rec tt_info[];
- extern char ttname[];
- #else
- #ifdef CK_AUTHENTICATION
- #include "ckuusr.h"
- #endif /* CK_AUTHENTICATION */
- #endif /* OS2 */
- #ifdef NT
- extern int winsock_version;
- #endif /* NT */
- #ifdef CK_AUTHENTICATION
- #include "ckuath.h"
- #endif /* CK_AUTHENTICATION */
- #include "ckcsig.h"
- #ifndef OS2 /* For timeout longjumps */
- static ckjmpbuf njbuf;
- #endif /* OS2 */
- #define NAMECPYL 1024 /* Local copy of hostname */
- char namecopy[NAMECPYL]; /* Referenced by ckctel.c */
- char namecopy2[NAMECPYL]; /* Referenced by ckctel.c */
- #ifndef NOHTTP
- char http_host_port[NAMECPYL]; /* orig host/port necessary for http */
- char http_ip[20] = { '\0' }; /* ip address of host */
- char http_port = 0;
- int http_ssl = 0;
- char * http_agent = 0;
- int httpfd = -1; /* socket for http connections */
- int http_code = 0;
- #define HTTPBUFLEN 1024
- char http_reply_str[HTTPBUFLEN] = "";
- #endif /* NOHTTP */
- char ipaddr[20] = { '\0' }; /* Global copy of IP address */
- unsigned long myxipaddr = 0L; /* Ditto as a number */
- #endif /* NETCONN */
- char *tcp_address = NULL; /* Preferred IP Address */
- extern char uidbuf[]; /* User ID buffer */
- extern char pwbuf[]; /* Password buffer */
- #ifndef NOHTTP
- char * tcp_http_proxy = NULL; /* Name[:port] of http proxy server */
- int tcp_http_proxy_errno = 0;
- char * tcp_http_proxy_user = NULL;
- char * tcp_http_proxy_pwd = NULL;
- char * tcp_http_proxy_agent = NULL;
- #define HTTPCPYL 1024
- static char proxycopy[HTTPCPYL];
- #endif /* NOHTTP */
- #ifdef OS2
- extern int tt_rows[], tt_cols[];
- extern int tt_status[VNUM];
- #else /* OS2 */
- extern int tt_rows, tt_cols; /* Everybody has this */
- #endif /* OS2 */
- extern int cmd_cols, cmd_rows;
- #ifdef STREAMING /* Use blocking writes for streaming */
- extern int streaming;
- #endif /* STREAMING */
- #ifdef NT
- extern int WSASafeToCancel;
- int win95selectbug = 0; /* For TCP/IP stacks whose select() */
- /* always fails on write requests such as Cisco and Quarterdeck */
- #define stricmp _stricmp
- #endif /* NT */
- #ifndef NOTCPOPTS
- /* Skip all this if NOTCPOPTS specified. */
- #ifdef SOL_SOCKET
- #ifdef TCP_NODELAY
- int tcp_nodelay = 0; /* Nagle algorithm TCP_NODELAY */
- #endif /* TCP_NODELAY */
- #ifdef SO_DONTROUTE
- int tcp_dontroute = 0;
- #endif /* SO_DONTROUTE */
- #ifdef SO_LINGER
- int tcp_linger = 0; /* SO_LINGER */
- int tcp_linger_tmo = 0; /* SO_LINGER timeout */
- #endif /* SO_LINGER */
- #ifdef HPUX /* But the data structures */
- #ifndef HPUX8 /* needed for linger are not */
- #ifndef HPUX9 /* defined in HP-UX versions */
- #ifndef HPUX10 /* prior to 8.00. */
- #ifdef SO_LINGER
- #undef SO_LINGER
- #endif /* SO_LINGER */
- #endif /* HPUX10 */
- #endif /* HPUX9 */
- #endif /* HPUX8 */
- #endif /* HPUX */
- #ifndef SO_OOBINLINE /* Hopefully only HP-UX 7.0 */
- #define SO_OOBINLINE 0x0100
- #endif /* SO_OOBINLINE */
- #ifndef TCPSNDBUFSIZ
- #ifdef VMS
- #ifdef __alpha
- #define TCPSNDBUFSIZ 16384
- #endif /* __alpha */
- #endif /* VMS */
- #endif /* TCPSNDBUFSIZ */
- #ifndef TCPSNDBUFSIZ
- #define TCPSNDBUFSIZ -1
- #endif /* TCPSNDBUFSIZ */
- #ifdef SO_SNDBUF
- int tcp_sendbuf = TCPSNDBUFSIZ;
- #endif /* SO_SNDBUF */
- #ifdef SO_RCVBUF
- int tcp_recvbuf = -1;
- #endif /* SO_RCVBUF */
- #ifdef SO_KEEPALIVE
- int tcp_keepalive = 1;
- #endif /* SO_KEEPALIVE */
- #endif /* SOL_SOCKET */
- #endif /* NOTCPOPTS */
- #ifndef NETCONN
- /*
- Network support not defined.
- Dummy functions here in case #ifdef's forgotten elsewhere.
- */
- int /* Open network connection */
- netopen(name, lcl, nett) char *name; int *lcl, nett; {
- return(-1);
- }
- int /* Close network connection */
- netclos() {
- return(-1);
- }
- int /* Check network input buffer */
- nettchk() {
- return(-1);
- }
- int /* Flush network input buffer */
- netflui() {
- return(-1);
- }
- int /* Send network BREAK */
- netbreak() {
- return(-1);
- }
- int /* Input character from network */
- netinc(timo) int timo; {
- return(-1);
- }
- int /* Output character to network */
- #ifdef CK_ANSIC
- nettoc(CHAR c)
- #else
- nettoc(c) CHAR c;
- #endif /* CK_ANSIC */
- /* nettoc */ {
- return(-1);
- }
- int
- nettol(s,n) CHAR *s; int n; {
- return(-1);
- }
- #else /* NETCONN is defined (much of this module...) */
- #ifdef NETLEBUF
- VOID
- le_init() { /* LocalEchoInit() */
- int i;
- for (i = 0; i < LEBUFSIZ; i++)
- le_buf[i] = '\0';
- le_start = 0;
- le_end = 0;
- le_data = 0;
- tt_push_inited = 1;
- }
- VOID
- le_clean() { /* LocalEchoCleanup() */
- le_init();
- return;
- }
- int
- le_inbuf() {
- int rc = 0;
- if (le_start != le_end) {
- rc = (le_end -
- le_start +
- LEBUFSIZ) % LEBUFSIZ;
- }
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- le_putchar(CHAR ch)
- #else
- le_putchar(ch) CHAR ch;
- #endif /* CK_ANSIC */
- /* le_putchar */ {
- if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
- debug(F110,"le_putchar","buffer is full",0);
- return(-1);
- }
- le_buf[le_end++] = ch;
- if (le_end == LEBUFSIZ)
- le_end = 0;
- le_data = 1;
- return(0);
- }
- int
- #ifdef CK_ANSIC
- le_puts(CHAR * s, int n)
- #else
- le_puts(s,n) CHAR * s; int n;
- #endif /* CK_ANSIC */
- /* le_puts */ {
- int rc = 0;
- int i = 0;
- CHAR * p = (CHAR *)"le_puts";
- ckhexdump(p,s,n);
- for (i = 0; i < n; i++)
- rc = le_putchar((char)s[i]);
- debug(F101,"le_puts","",rc);
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- le_putstr(CHAR * s)
- #else
- le_putstr(s) CHAR * s;
- #endif /* CK_ANSIC */
- /* le_puts */ {
- CHAR * p;
- int rc = 0;
- p = (CHAR *)"le_putstr";
- ckhexdump(p,s,(int)strlen((char *)s));
- for (p = s; *p && !rc; p++)
- rc = le_putchar(*p);
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- le_getchar(CHAR * pch)
- #else /* CK_ANSIC */
- le_getchar(pch) CHAR * pch;
- #endif /* CK_ANSIC */
- /* le_gatchar */ {
- int rc = 0;
- if (le_start != le_end) {
- *pch = le_buf[le_start];
- le_buf[le_start] = 0;
- le_start++;
- if (le_start == LEBUFSIZ)
- le_start = 0;
- if (le_start == le_end) {
- le_data = 0;
- }
- rc++;
- } else {
- *pch = 0;
- }
- return(rc);
- }
- #endif /* NETLEBUF */
- #ifdef VMS
- /*
- In edit 190, we moved tn_ini() to be called from within netopen().
- But tn_ini() calls ttol(), and ttol() checks to see if it's a net
- connection, but the flag for that isn't set until after netopen()
- is finished. Since, in this module, we are always doing network
- output anyway, we just call nettol() directly, instead of going thru
- ttol(). Only needed for VMS, since UNIX, AOS/VS, and VOS can handle
- net connections just like regular connections in ttol(), and OS/2
- has a special routine for this.
- */
- #define ttol nettol
- #endif /* VMS */
- int tcpsrfd = -1;
- #ifdef CK_KERBEROS
- char * krb5_d_principal = NULL; /* Default principal */
- char * krb5_d_instance = NULL; /* Default instance */
- char * krb5_d_realm = NULL; /* Default realm */
- char * krb5_d_cc = NULL; /* Default credentials cache */
- char * krb5_d_srv = NULL; /* Default Service */
- int krb5_d_lifetime = 600; /* Default lifetime (10 hours) */
- int krb5_d_forwardable = 0; /* creds not forwardable */
- int krb5_d_proxiable = 0; /* creds not proxiable */
- int krb5_d_renewable = 0; /* creds not renewable (0 min) */
- int krb5_autoget = 1; /* Autoget TGTs */
- int krb5_autodel = 0; /* Auto delete TGTs */
- int krb5_d_getk4 = 0; /* K5 Kinit gets K4 TGTs */
- int krb5_checkaddrs = 1; /* Check TGT Addrs */
- int krb5_d_no_addresses = 0; /* Do not include IP Addresses */
- char * krb5_d_addrs[KRB5_NUM_OF_ADDRS+1]={NULL,NULL}; /* Addrs to include */
- int krb5_errno = 0; /* Last K5 errno */
- char * krb5_errmsg = NULL; /* Last K5 errmsg */
- char * k5_keytab = NULL;
- char * krb4_d_principal = NULL; /* Default principal */
- char * krb4_d_realm = NULL; /* Default realm */
- char * krb4_d_srv = NULL; /* Default Service */
- int krb4_d_lifetime = 600; /* Default lifetime (10 hours) */
- int krb4_d_preauth = 1; /* Use preauth requests */
- char * krb4_d_instance = NULL; /* Default instance */
- int krb4_autoget = 1; /* Autoget TGTs */
- int krb4_autodel = 0; /* Auto delete TGTs */
- int krb4_checkaddrs = 1; /* Check TGT Addrs */
- char * k4_keytab = NULL;
- int krb4_errno = 0; /* Last K4 errno */
- char * krb4_errmsg = NULL; /* Last K4 errmsg */
- struct krb_op_data krb_op = { /* Operational data structure */
- 0, NULL /* (version, cachefile) */
- };
- struct krb4_init_data krb4_init = { /* Kerberos 4 INIT data structure */
- 0, NULL, NULL, NULL, NULL
- };
- struct krb5_init_data krb5_init = { /* Kerberos 5 INIT data structure */
- 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0,
- { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
- 0
- };
- struct krb5_list_cred_data krb5_lc = { /* List Credentials data structure */
- 0, 0, 0
- };
- int krb_action = -1; /* Kerberos action to perform */
- #ifndef CK_AUTHENTICATION
- char *
- ck_krb4_getrealm() {
- return("");
- }
- char *
- ck_krb5_getrealm(cc) char * cc; {
- return("");
- }
- char *
- ck_krb4_getprincipal() {
- return("");
- }
- char *
- ck_krb5_getprincipal(cc) char * cc; {
- return("");
- }
- #endif /* CK_AUTHENTICATION */
- /* I N I _ K E R B -- Initialize Kerberos data */
- VOID
- ini_kerb() {
- int i;
- krb_action = -1; /* No action specified */
- krb_op.version = 0; /* Kerberos version (none) */
- krb_op.cache = NULL; /* Cache file (none) */
- /* Kerberos 5 */
- krb5_init.forwardable = krb5_d_forwardable; /* Init switch values... */
- krb5_init.proxiable = krb5_d_proxiable;
- krb5_init.lifetime = krb5_d_lifetime;
- krb5_init.renew = 0;
- krb5_init.renewable = krb5_d_renewable;
- krb5_init.validate = 0;
- krb5_init.no_addresses = krb5_d_no_addresses;
- krb5_init.getk4 = krb5_d_getk4;
- if (krb5_init.postdate) {
- free(krb5_init.postdate);
- krb5_init.postdate = NULL;
- }
- if (krb5_init.service) {
- free(krb5_init.service);
- krb5_init.service = NULL;
- }
- if (!krb5_d_cc || !krb5_d_cc[0]) { /* Set default cache */
- char * p;
- p = ck_krb5_get_cc_name();
- makestr(&krb5_d_cc,(p && p[0]) ? p : NULL);
- }
- if (!krb5_d_realm || !krb5_d_realm[0]) { /* Set default realm */
- char * p;
- p = ck_krb5_getrealm(krb5_d_cc);
- makestr(&krb5_d_realm,(p && p[0]) ? p : NULL);
- }
- makestr(&krb5_init.instance,krb5_d_instance);
- makestr(&krb5_init.realm,krb5_d_realm); /* Set realm from default */
- if (krb5_init.password) {
- memset(krb5_init.password,0xFF,strlen(krb5_init.password));
- free(krb5_init.password);
- krb5_init.password = NULL;
- }
- if (!krb5_d_principal) { /* Default principal */
- /* a Null principal indicates the user should be prompted */
- char * p = ck_krb5_getprincipal(krb5_d_cc);
- if (!p || !(*p))
- p = (char *)uidbuf; /* Principal = user */
- makestr(&krb5_d_principal,(p && p[0]) ? p : NULL);
- }
- makestr(&krb5_init.principal,krb5_d_principal);
- for (i = 0; i <= KRB5_NUM_OF_ADDRS; i++) {
- if (krb5_init.addrs[i])
- free(krb5_init.addrs[i]);
- krb5_init.addrs[i] = NULL;
- }
- for (i = 0; i <= KRB5_NUM_OF_ADDRS && krb5_d_addrs[i]; i++) {
- makestr(&krb5_init.addrs[i],krb5_d_addrs[i]);
- }
- /* Kerberos 4 */
- krb4_init.lifetime = krb4_d_lifetime;
- krb4_init.preauth = krb4_d_preauth;
- makestr(&krb4_init.instance,krb4_d_instance);
- if (!krb4_d_realm || !krb4_d_realm[0]) {/* Set default realm */
- char * p;
- p = ck_krb4_getrealm();
- makestr(&krb4_d_realm,(p && p[0]) ? p : NULL);
- }
- makestr(&krb4_init.realm,krb4_d_realm);
- if (krb4_init.password) {
- memset(krb4_init.password,0xFF,strlen(krb4_init.password));
- free(krb4_init.password);
- krb4_init.password = NULL;
- }
- if (!krb4_d_principal) { /* Default principal */
- /* a Null principal indicates the user should be prompted */
- char * p = ck_krb4_getprincipal();
- if (!p || !(*p))
- p = (char *)uidbuf; /* Principal = user */
- makestr(&(krb4_d_principal),(p && p[0]) ? p : NULL);
- }
- makestr(&(krb4_init.principal),krb4_d_principal);
- }
- /* D O A U T H -- AUTHENTICATE action routine */
- int
- doauth(cx) int cx; { /* AUTHENTICATE action routine */
- int rc = 0; /* Return code */
- #ifdef CK_AUTHENTICATION
- #ifdef OS2
- if (!ck_security_loaddll()) /* Load various DLLs */
- return(rc);
- #endif /* OS2 */
- if (krb_op.version == 4) { /* Version = 4 */
- #ifdef COMMENT
- sho_auth(AUTHTYPE_KERBEROS_V4);
- #endif /* COMMENT */
- if (!ck_krb4_is_installed()) {
- printf("?Kerberos 4 is not installed\n");
- return(0);
- }
- switch (krb_action) { /* Perform V4 functions */
- case KRB_A_IN: /* INIT */
- rc |= !(ck_krb4_initTGT(&krb_op,&krb4_init) < 0);
- break;
- case KRB_A_DE: /* DESTROY */
- rc |= !(ck_krb4_destroy(&krb_op) < 0);
- break;
- case KRB_A_LC: /* LIST-CREDENTIALS */
- rc |= !(ck_krb4_list_creds(&krb_op) < 0);
- break;
- }
- }
- if (krb_op.version == 5) { /* V5 functions */
- #ifdef COMMENT
- sho_auth(AUTHTYPE_KERBEROS_V5);
- #endif /* COMMENT */
- if (!ck_krb5_is_installed()) {
- printf("?Kerberos 5 is not installed\n");
- return(0);
- }
- switch (krb_action) {
- case KRB_A_IN: /* INIT */
- rc |= !(ck_krb5_initTGT(&krb_op,&krb5_init,
- krb5_init.getk4 ? &krb4_init : 0) < 0);
- break;
- case KRB_A_DE: /* DESTROY */
- rc |= !(ck_krb5_destroy(&krb_op) < 0);
- break;
- case KRB_A_LC: /* LIST-CREDENTIALS */
- if (krb_op.version == 0)
- printf("\n");
- rc |= !(ck_krb5_list_creds(&krb_op,&krb5_lc) < 0);
- break;
- }
- }
- #else
- #ifndef NOICP
- #ifndef NOSHOW
- rc = sho_auth(0); /* Show all */
- #endif /* NOSHOW */
- #endif /* NOICP */
- #endif /* CK_AUTHENTICATION */
- return(rc);
- }
- #endif /* CK_KERBEROS */
- #ifdef TCPSOCKET
- #ifndef OS2
- #ifndef NOLISTEN /* For incoming connections */
- #ifndef INADDR_ANY
- #define INADDR_ANY 0
- #endif /* INADDR_ANY */
- _PROTOTYP( int ttbufr, ( VOID ) );
- _PROTOTYP( int tcpsrv_open, (char *, int *, int, int ) );
- static unsigned short tcpsrv_port = 0;
- #endif /* NOLISTEN */
- #endif /* OS2 */
- static char svcbuf[80]; /* TCP service string */
- static int svcnum = 0; /* TCP port number */
- #endif /* TCPSOCKET */
- /*
- TCPIPLIB means use separate socket calls for i/o, while on UNIX the
- normal file system calls are used for TCP/IP sockets too.
- Means "DEC_TCPIP or MULTINET or WINTCP or OS2 or BEBOX" (see ckcnet.h),
- */
- #ifdef TCPIPLIB
- /* For buffered network reads... */
- /*
- If the buffering code is written right, it shouldn't matter
- how long this buffer is.
- */
- #ifdef OS2
- #ifdef NT
- #define TTIBUFL 64240 /* 44 * 1460 (MSS) */
- #else
- #define TTIBUFL 32120 /* 22 * 1460 (MSS) */
- #endif /* NT */
- #else /* OS2 */
- #define TTIBUFL 8191 /* Let's use 8K. */
- #endif /* OS2 */
- CHAR ttibuf[TTIBUFL+1];
- /*
- select() is used in preference to alarm()/signal(), but different systems
- use different forms of select()...
- */
- #ifndef NOSELECT /* Option to override BSDSELECT */
- #ifdef BELLV10
- /*
- Note: Although BELLV10 does have TCP/IP support, and does use the unique
- form of select() that is evident in this module (and in ckutio.c), it does
- not have a sockets library and so we can't build Kermit TCP/IP support for
- it. For this, somebody would have to write TCP/IP streams code.
- */
- #define BELLSELECT
- #ifndef FD_SETSIZE
- #define FD_SETSIZE 128
- #endif /* FD_SETSIZE */
- #else
- #ifdef WINTCP /* VMS with Wollongong WIN/TCP */
- #ifndef OLD_TWG /* TWG 3.2 has only select(read) */
- #define BSDSELECT
- #endif /* OLD_TWG */
- #else
- #ifdef CMU_TCPIP /* LIBCMU can do select */
- #define BSDSELECT
- #else
- #ifdef DEC_TCPIP
- #define BSDSELECT
- #else
- #ifdef OS2 /* OS/2 with TCP/IP */
- #ifdef NT
- #define BSDSELECT
- #else /* NT */
- #define IBMSELECT
- #endif /* NT */
- #endif /* OS2 */
- #endif /* DEC_TCPIP */
- #endif /* CMU_TCPIP */
- #endif /* WINTCP */
- #endif /* BELLV10 */
- #endif /* NOSELECT */
- /*
- Others (TGV, TCPware, ...) use alarm()/signal(). The BSDSELECT case does not
- compile at all; the IBMSELECT case compiles and links but crashes at runtime.
- NOTE: If any of these can be converted to select(), they should be for two
- reasons: (1) It's a lot faster; (2) certain sockets libraries do not like
- their socket_read() calls to be interrupted; subsequent socket_read()'s tend
- to fail with EBUSY. This happened in the UCX case before it was converted
- to use select().
- */
- #ifndef OS2
- #ifndef VMS
- static /* These are used in CKVTIO.C */
- #endif /* VMS */ /* And in CKONET.C */
- #endif /* OS2 */
- int
- ttibp = 0,
- ttibn = 0;
- /*
- Read bytes from network into internal buffer ttibuf[].
- To be called when input buffer is empty, i.e. when ttibn == 0.
- Other network reading routines, like ttinc, ttinl, ttxin, should check the
- internal buffer first, and call this routine for a refill if necessary.
- Returns -1 on error, 0 if nothing happens. When data is read successfully,
- returns number of bytes read, and sets global ttibn to that number and
- ttibp (the buffer pointer) to zero.
- */
- _PROTOTYP( int ttbufr, ( VOID ) );
- int
- ttbufr() { /* TT Buffer Read */
- int count;
- if (ttnet != NET_TCPB) /* First make sure current net is */
- return(-1); /* TCP/IP; if not, do nothing. */
- #ifdef OS2
- RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
- #endif /* OS2 */
- if (ttibn > 0) { /* Our internal buffer is not empty, */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(ttibn); /* so keep using it. */
- }
- if (ttyfd == -1) { /* No connection, error */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- ttibp = 0; /* Else reset pointer to beginning */
- #ifdef WINTCP
- count = 512; /* This works for WIN/TCP */
- #else
- #ifdef DEC_TCPIP
- count = 512; /* UCX */
- #else
- #ifdef OS2
- count = TTIBUFL;
- #else /* Multinet, etc. */
- count = ttchk(); /* Check network input buffer, */
- if (ttibn > 0) { /* which can put a char there! */
- debug(F111,"ttbufr","ttchk() returns",count);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(ttibn);
- }
- if (count < 0) { /* Read error - connection closed */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- else if (count > TTIBUFL) /* Too many to read */
- count = TTIBUFL;
- else if (count == 0) /* None, so force blocking read */
- count = 1;
- #endif /* OS2 */
- #endif /* DEC_TCPIP */
- #endif /* WINTCP */
- debug(F101,"ttbufr count 1","",count);
- #ifdef CK_SSL
- if (ssl_active_flag || tls_active_flag) {
- int error;
- ssl_read:
- if (ssl_active_flag)
- count = SSL_read(ssl_con, ttibuf, count);
- else
- count = SSL_read(tls_con, ttibuf, count);
- error = SSL_get_error(ssl_active_flag?ssl_con:tls_con,count);
- switch (error) {
- case SSL_ERROR_NONE:
- debug(F111,"ttbufr SSL_ERROR_NONE","count",count);
- if (count > 0) {
- ttibp = 0; /* Reset buffer pointer. */
- ttibn = count;
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(ttibn); /* Return buffer count. */
- } else if (count < 0) {
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- } else {
- netclos();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- case SSL_ERROR_WANT_WRITE:
- debug(F100,"ttbufr SSL_ERROR_WANT_WRITE","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- case SSL_ERROR_WANT_READ:
- debug(F100,"ttbufr SSL_ERROR_WANT_READ","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- case SSL_ERROR_SYSCALL:
- if ( count == 0 ) { /* EOF */
- netclos();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- } else {
- int rc = -1;
- #ifdef NT
- int gle = GetLastError();
- debug(F111,"ttbufr SSL_ERROR_SYSCALL",
- "GetLastError()",gle);
- rc = os2socketerror(gle);
- if (rc == -1)
- rc = -2;
- else if ( rc == -2 )
- rc = -1;
- #endif /* NT */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(rc);
- }
- case SSL_ERROR_WANT_X509_LOOKUP:
- debug(F100,"ttbufr SSL_ERROR_WANT_X509_LOOKUP","",0);
- netclos();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- case SSL_ERROR_SSL:
- if (bio_err!=NULL) {
- int len;
- extern char ssl_err[];
- BIO_printf(bio_err,"ttbufr SSL_ERROR_SSL\n");
- ERR_print_errors(bio_err);
- len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
- ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
- debug(F110,"ttbufr SSL_ERROR_SSL",ssl_err,0);
- if (ssl_debug_flag)
- printf(ssl_err);
- } else if (ssl_debug_flag) {
- debug(F100,"ttbufr SSL_ERROR_SSL","",0);
- fflush(stderr);
- fprintf(stderr,"ttbufr SSL_ERROR_SSL\n");
- ERR_print_errors_fp(stderr);
- }
- #ifdef COMMENT
- netclos();
- #endif /* COMMENT */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- case SSL_ERROR_ZERO_RETURN:
- debug(F100,"ttbufr SSL_ERROR_ZERO_RETURN","",0);
- netclos();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- default:
- debug(F100,"ttbufr SSL_ERROR_?????","",0);
- netclos();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- }
- #endif /* CK_SSL */
- #ifdef COMMENT
- /*
- This is for nonblocking reads, which we don't do any more. This code didn't
- work anyway, in the sense that a broken connection was never sensed.
- */
- if ((count = socket_read(ttyfd,&ttibuf[ttibp+ttibn],count)) < 1) {
- if (count == -1 && socket_errno == EWOULDBLOCK) {
- debug(F100,"ttbufr finds nothing","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(0);
- } else {
- debug(F101,"ttbufr socket_read error","",socket_errno);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- }
- } else if (count == 0) {
- debug(F100,"ttbufr socket eof","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- }
- #else /* COMMENT */
- /* This is for blocking reads */
- #ifndef VMS
- #ifdef SO_OOBINLINE
- {
- int outofband = 0;
- #ifdef BELLSELECT
- if (select(128, NULL, NULL, efds, 0) > 0 && FD_ISSET(ttyfd, efds))
- outofband = 1;
- #else
- #ifdef BSDSELECT
- fd_set efds;
- struct timeval tv;
- FD_ZERO(&efds);
- FD_SET(ttyfd, &efds);
- tv.tv_sec = tv.tv_usec = 0L;
- debug(F100,"Out-of-Band BSDSELECT","",0);
- #ifdef NT
- WSASafeToCancel = 1;
- #endif /* NT */
- if (select(FD_SETSIZE, NULL, NULL, &efds, &tv) > 0 &&
- FD_ISSET(ttyfd, &efds))
- outofband = 1;
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- #else /* !BSDSELECT */
- #ifdef IBMSELECT
- /* Is used by OS/2 ... */
- /* ... and it came in handy! For our TCP/IP layer, it avoids all the fd_set */
- /* and timeval stuff since this is the only place where it is used. */
- int socket = ttyfd;
- debug(F100,"Out-of-Band IBMSELECT","",0);
- if ((select(&socket, 0, 0, 1, 0L) == 1) && (socket == ttyfd))
- outofband = 1;
- #else /* !IBMSELECT */
- /*
- If we can't use select(), then we use the regular alarm()/signal()
- timeout mechanism.
- */
- debug(F101,"Out-of-Band data not supported","",0);
- outofband = 0;
- #endif /* IBMSELECT */
- #endif /* BSDSELECT */
- #endif /* BELLSELECT */
- if (outofband) {
- /* Get the Urgent Data */
- /* if OOBINLINE is disabled this should be only a single byte */
- /* MS Winsock has a bug in Windows 95. Extra bytes are delivered */
- /* That were never sent. */
- #ifdef OS2
- RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
- #endif /* OS2 */
- count = socket_recv(ttyfd,&ttibuf[ttibp+ttibn],count,MSG_OOB);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- if (count <= 0) {
- int s_errno = socket_errno;
- debug(F101, "ttbufr socket_recv MSG_OOB","",count);
- debug(F101, "ttbufr socket_errno","",s_errno);
- #ifdef OS2ONLY
- if (count < 0 && (s_errno == 0 || s_errno == 23)) {
- /* These appear in OS/2 - don't know why */
- /* ignore it and read as normal data */
- /* and break, then we will attempt to read */
- /* the port using normal read() techniques */
- debug(F100,"ttbufr handing as in-band data","",0);
- count = 1;
- } else {
- netclos(); /* *** *** */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- #else /* OS2ONLY */
- netclos(); /* *** *** */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- #endif /* OS2ONLY */
- } else { /* we got out-of-band data */
- ckhexdump("ttbufr out-of-band chars",&ttibuf[ttibp+ttibn],count);
- #ifdef BETADEBUG
- bleep(BP_NOTE);
- #endif /* BETADEBUG */
- #ifdef RLOGCODE /* blah */
- if (ttnproto == NP_RLOGIN ||
- ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN ||
- ((ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN) &&
- !rlog_inband)
- )
- {
- /*
- When urgent data is read with MSG_OOB and not OOBINLINE
- then urgent data and normal data are not mixed. So
- treat the entire buffer as urgent data.
- */
- rlog_oob(&ttibuf[ttibp+ttibn], count);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return ttbufr();
- } else
- #endif /* RLOGCODE */ /* blah */
- #ifdef COMMENT
- /*
- I haven't written this yet, nor do I know what it should do
- */
- if (ttnproto == NP_TELNET) {
- tn_oob();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return 0;
- } else
- #endif /* COMMENT */
- {
- /* For any protocols we don't have a special out-of-band */
- /* handler for, just put the bytes in the normal buffer */
- /* and return */
- ttibp += 0; /* Reset buffer pointer. */
- ttibn += count;
- #ifdef DEBUG
- /* Got some bytes. */
- debug(F101,"ttbufr count 2","",count);
- if (count > 0)
- ttibuf[ttibp+ttibn] = '\0';
- debug(F111,"ttbufr ttibuf",ttibuf,ttibp);
- #endif /* DEBUG */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(ttibn); /* Return buffer count. */
- }
- }
- }
- }
- #endif /* SO_OOBINLINE */
- #endif /* VMS */
- count = socket_read(ttyfd,&ttibuf[ttibp+ttibn],count);
- if (count <= 0) {
- int s_errno = socket_errno;
- debug(F101,"ttbufr socket_read","",count);
- debug(F101,"ttbufr socket_errno","",s_errno);
- #ifdef OS2
- if (count == 0 || os2socketerror(s_errno) < 0) {
- netclos();
- ReleaseTCPIPMutex();
- return(-2);
- }
- ReleaseTCPIPMutex();
- return(-1);
- #else /* OS2 */
- netclos(); /* *** *** */
- return(-2);
- #endif /* OS2 */
- }
- #endif /* COMMENT */ /* (blocking vs nonblock reads...) */
- else {
- ttibp = 0; /* Reset buffer pointer. */
- ttibn += count;
- #ifdef DEBUG
- debug(F101,"ttbufr count 2","",count); /* Got some bytes. */
- if (count > 0)
- ttibuf[ttibp+ttibn] = '\0';
- debug(F111,"ttbufr ttibuf",&ttibuf[ttibp],ttibn);
- #endif /* DEBUG */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(ttibn); /* Return buffer count. */
- }
- }
- #endif /* TCPIPLIB */
- #ifndef IBMSELECT
- #ifndef BELLSELECT
- #ifndef BSDSELECT /* Non-TCPIPLIB case */
- #ifdef SELECT
- #define BSDSELECT
- #endif /* SELECT */
- #endif /* BSDSELECT */
- #endif /* BELLSELECT */
- #endif /* IBMSELECT */
- #define TELNET_PORT 23 /* Should do lookup, but it won't change */
- #define RLOGIN_PORT 513
- #define KERMIT_PORT 1649
- #define KLOGIN_PORT 543
- #define EKLOGIN_PORT 2105
- #ifndef NONET
- /*
- C-Kermit network open/close functions for BSD-sockets.
- Much of this code shared by SunLink X.25, which also uses the socket library.
- */
- /* N E T O P N -- Open a network connection. */
- /*
- Call with:
- name of host (or host:service),
- lcl - local-mode flag to be set if this function succeeds,
- network type - value defined in ckunet.h.
- */
- #ifdef TCPSOCKET
- struct hostent *
- #ifdef CK_ANSIC
- ck_copyhostent(struct hostent * h)
- #else /* CK_ANSIC */
- ck_copyhostent(h) struct hostent * h;
- #endif /* CK_ANSIC */
- {
- /*
- * The hostent structure is dynamic in nature.
- * struct hostent {
- * char * h_name;
- * char * * h_aliases;
- * short h_addrtype;
- * short h_length;
- * char * * h_addr_list;
- * #define h_addr h_addr_list[0]
- */
- #define HOSTENTCNT 5
- static struct hostent hosts[HOSTENTCNT] = {{NULL,NULL,0,0,NULL},
- {NULL,NULL,0,0,NULL},
- {NULL,NULL,0,0,NULL},
- {NULL,NULL,0,0,NULL},
- {NULL,NULL,0,0,NULL}};
- static int next = 0;
- int i,cnt;
- char ** pp;
- if ( h == NULL )
- return(NULL);
- if (next == HOSTENTCNT)
- next = 0;
- if ( hosts[next].h_name ) {
- free(hosts[next].h_name);
- hosts[next].h_name = NULL;
- }
- if ( hosts[next].h_aliases ) {
- pp = hosts[next].h_aliases;
- while ( *pp ) {
- free(*pp);
- pp++;
- }
- free(hosts[next].h_aliases);
- }
- #ifdef HADDRLIST
- if ( hosts[next].h_addr_list ) {
- pp = hosts[next].h_addr_list;
- while ( *pp ) {
- free(*pp);
- pp++;
- }
- free(hosts[next].h_addr_list);
- }
- #endif /* HADDRLIST */
- makestr(&hosts[next].h_name,h->h_name);
- if (h->h_aliases) {
- for ( cnt=0,pp=h->h_aliases; pp && *pp; pp++,cnt++) ;
- /* The following can give warnings in non-ANSI builds */
- hosts[next].h_aliases = (char **) malloc(sizeof(char *) * (cnt+1));
- for ( i=0; i<cnt; i++) {
- hosts[next].h_aliases[i] = NULL;
- makestr(&hosts[next].h_aliases[i],h->h_aliases[i]);
- }
- hosts[next].h_aliases[i] = NULL;
- } else
- hosts[next].h_aliases = NULL;
- hosts[next].h_addrtype = h->h_addrtype;
- hosts[next].h_length = h->h_length;
- #ifdef HADDRLIST
- #ifdef h_addr
- if (h->h_addr_list) {
- for ( cnt=0,pp=h->h_addr_list; pp && *pp; pp++,cnt++) ;
- /* The following can give warnings non-ANSI builds */
- hosts[next].h_addr_list = (char **) malloc(sizeof(char *) * (cnt+1));
- for ( i=0; i<cnt; i++) {
- hosts[next].h_addr_list[i] = malloc(h->h_length);
- bcopy(h->h_addr_list[i],hosts[next].h_addr_list[i],h->h_length);
- }
- hosts[next].h_addr_list[i] = NULL;
- } else
- hosts[next].h_addr_list = NULL;
- #else
- bcopy(h->h_addr, &hosts[next].h_addr, h->h_length);
- #endif /* h_addr */
- #else /* HADDRLIST */
- bcopy(h->h_addr, &hosts[next].h_addr, h->h_length);
- #endif /* HADDRLIST */
- return(&hosts[next++]);
- }
- #ifdef EXCELAN
- /*
- Most other BSD sockets implementations define these in header files
- and libraries.
- */
- struct servent {
- unsigned short s_port;
- };
- struct hostent {
- short h_addrtype;
- struct in_addr h_addr;
- int h_length;
- };
- struct servent *
- getservbyname(service, connection) char *service,*connection; {
- static struct servent servrec;
- int port;
- port = 0;
- if (strcmp(service, "telnet") == 0) port = 23;
- else if (strcmp(service, "smtp") == 0) port = 25;
- else port = atoi(service);
- debug(F101,"getservbyname return port ","",port);
- if (port > 0) {
- servrec.s_port = htons(port);
- return(&servrec);
- }
- return((struct servent *) NULL);
- }
- struct hostent *
- gethostbyname(hostname) char *hostname; {
- return((struct hostent *) NULL);
- }
- unsigned long
- inet_addr(name) char *name; {
- unsigned long addr;
- addr = rhost(&name);
- debug(F111,"inet_addr ",name,(int)addr);
- return(addr);
- }
- char *
- inet_ntoa(in) struct in_addr in; {
- static char name[80];
- ckmakxmsg(name, ckuitoa(in.s_net),".",ckuitoa(in.s_host),".",
- ckuitoa(in.s_lh),".", ckuitoa(in.s_impno));
- return(name);
- }
- #else
- #ifdef DEC_TCPIP /* UCX */
- int ucx_port_bug = 0; /* Explained below */
- #ifdef OLDIP /* Very old VAXC or GCC */
- /*
- Note that my oldest VAX C (V3.1-051) does not need (or want) OLDIP,
- hence the "Very old" in the comment - SMS, 2010/03/15.
- */
- #define getservbyname my_getservbyname
- #ifdef CK_ANSIC
- globalref int (*C$$GA_UCX_GETSERVBYNAME)();
- extern void C$$TRANSLATE();
- extern void C$$SOCK_TRANSLATE();
- #else
- globalref int (*C$$GA_UCX_GETSERVBYNAME)();
- extern VOID C$$TRANSLATE();
- extern VOID C$$SOCK_TRANSLATE();
- #endif /* CK_ANSIC */
- struct servent *
- my_getservbyname (service, proto) char *service, *proto; {
- static struct servent sent;
- struct iosb {
- union {
- unsigned long status;
- unsigned short st[2];
- } sb;
- unsigned long spare;
- } s;
- struct {
- struct iosb *s;
- char *serv;
- char *prot;
- } par;
- unsigned long e;
- char sbuf[30], pbuf[30];
- char *p;
- debug(F111,"UCX getservbyname",service,(int)C$$GA_UCX_GETSERVBYNAME);
- p = sbuf;
- ckstrncpy(p, service, 29);
- while (*p = toupper(*p), *p++) {}
- p = pbuf;
- ckstrncpy(p, proto, 29);
- while (*p = toupper(*p), *p++) {}
- par.s = &s;
- par.serv = "";
- par.prot = "";
- /* reset file pointer or something like that!?!? */
- e = (*C$$GA_UCX_GETSERVBYNAME)(&par, &sent, par.s);
- par.serv = sbuf;
- par.prot = pbuf; /* that is don't care */
- e = (*C$$GA_UCX_GETSERVBYNAME)(&par, &sent, par.s);
- if ((long)e == -1L)
- return NULL;
- if ((e & 1) == 0L) {
- C$$TRANSLATE(e);
- return NULL;
- }
- if ((s.sb.st[0] & 1) == 0) {
- C$$SOCK_TRANSLATE(&s.sb.st[0]);
- return NULL;
- }
- /*
- sent.s_port is supposed to be returned by UCX in network byte order.
- However, UCX 2.0 through 2.0C did not do this; 2.0D and later do it.
- But there is no way of knowing which UCX version, so we have a user-settable
- runtime variable. Note: UCX 2.0 was only for the VAX.
- */
- debug(F101,"UCX getservbyname port","",sent.s_port);
- debug(F101,"UCX getservbyname ntohs(port)","",ntohs(sent.s_port));
- if (ucx_port_bug) {
- sent.s_port = htons(sent.s_port);
- debug(F100,"UCX-PORT-BUG ON: swapping bytes","",0);
- debug(F101,"UCX swapped port","",sent.s_port);
- debug(F101,"UCX swapped ntohs(port)","",ntohs(sent.s_port));
- }
- return &sent;
- }
- #endif /* def OLDIP */
- #endif /* DEC_TCPIP */
- #endif /* EXCELAN */
- int
- gettcpport() {
- return(svcnum);
- }
- #endif /* TCPSOCKET */
- #ifndef NOTCPOPTS
- #ifndef datageneral
- int
- ck_linger(sock, onoff, timo) int sock; int onoff; int timo; {
- /*
- The following, from William Bader, turns off the socket linger parameter,
- which makes a close() block until all data is sent. "I don't think that
- disabling linger can ever cause kermit to lose data, but you telnet to a
- flaky server (or to our modem server when the modem is in use), disabling
- linger prevents kermit from hanging on the close if you try to exit."
- Modified by Jeff Altman to be generally useful.
- */
- #ifdef SOL_SOCKET
- #ifdef SO_LINGER
- struct linger set_linger_opt;
- struct linger get_linger_opt;
- SOCKOPT_T x;
- #ifdef IKSD
- if (!inserver)
- #endif /* IKSD */
- if (sock == -1 ||
- nettype != NET_TCPA && nettype != NET_TCPB &&
- nettype != NET_SSH || ttmdm >= 0) {
- tcp_linger = onoff;
- tcp_linger_tmo = timo;
- return(1);
- }
- x = sizeof(get_linger_opt);
- if (getsockopt(sock, SOL_SOCKET, SO_LINGER,
- (char *)&get_linger_opt, &x)) {
- debug(F111,"TCP ck_linger can't get SO_LINGER",ck_errstr(),errno);
- } else if (x != sizeof(get_linger_opt)) {
- #ifdef OS2
- struct _linger16 {
- short s_linger;
- short s_onoff;
- } get_linger_opt16, set_linger_opt16;
- if ( x == sizeof(get_linger_opt16) ) {
- debug(F111,"TCP setlinger warning: SO_LINGER","len is 16-bit",x);
- if (getsockopt(sock,
- SOL_SOCKET, SO_LINGER,
- (char *)&get_linger_opt16, &x)
- ) {
- debug(F111,
- "TCP ck_linger can't get SO_LINGER",ck_errstr(),errno);
- } else if (get_linger_opt16.s_onoff != onoff ||
- get_linger_opt16.s_linger != timo)
- {
- set_linger_opt16.s_onoff = onoff;
- set_linger_opt16.s_linger = timo;
- if (setsockopt(sock,
- SOL_SOCKET,
- SO_LINGER,
- (char *)&set_linger_opt16,
- sizeof(set_linger_opt16))
- ) {
- debug(F111,
- "TCP ck_linger can't set SO_LINGER",
- ck_errstr(),
- errno
- );
- tcp_linger = get_linger_opt16.s_onoff;
- tcp_linger_tmo = get_linger_opt16.s_linger;
- } else {
- debug(F101,
- "TCP ck_linger new SO_LINGER","",
- set_linger_opt16.s_onoff);
- tcp_linger = set_linger_opt16.s_onoff;
- tcp_linger_tmo = set_linger_opt16.s_linger;
- return 1;
- }
- } else {
- debug(F101,"TCP ck_linger SO_LINGER unchanged","",
- get_linger_opt16.s_onoff);
- tcp_linger = get_linger_opt16.s_onoff;
- tcp_linger_tmo = get_linger_opt16.s_linger;
- return 1;
- }
- return(0);
- }
- #endif /* OS2 */
- debug(F111,"TCP ck_linger error: SO_LINGER","len",x);
- debug(F111,"TCP ck_linger SO_LINGER",
- "expected len",sizeof(get_linger_opt));
- debug(F111,"TCP ck_linger SO_LINGER","linger_opt.l_onoff",
- get_linger_opt.l_onoff);
- debug(F111,"TCP linger SO_LINGER","linger_opt.l_linger",
- get_linger_opt.l_linger);
- } else if (get_linger_opt.l_onoff != onoff ||
- get_linger_opt.l_linger != timo) {
- set_linger_opt.l_onoff = onoff;
- set_linger_opt.l_linger = timo;
- if (setsockopt(sock,
- SOL_SOCKET,
- SO_LINGER,
- (char *)&set_linger_opt,
- sizeof(set_linger_opt))) {
- debug(F111,"TCP ck_linger can't set SO_LINGER",ck_errstr(),errno);
- tcp_linger = get_linger_opt.l_onoff;
- tcp_linger_tmo = get_linger_opt.l_linger;
- } else {
- debug(F101,
- "TCP ck_linger new SO_LINGER",
- "",
- set_linger_opt.l_onoff
- );
- tcp_linger = set_linger_opt.l_onoff;
- tcp_linger_tmo = set_linger_opt.l_linger;
- return 1;
- }
- } else {
- debug(F101,"TCP ck_linger SO_LINGER unchanged","",
- get_linger_opt.l_onoff);
- tcp_linger = get_linger_opt.l_onoff;
- tcp_linger_tmo = get_linger_opt.l_linger;
- return 1;
- }
- #else
- debug(F100,"TCP ck_linger SO_LINGER not defined","",0);
- #endif /* SO_LINGER */
- #else
- debug(F100,"TCP ck_linger SO_SOCKET not defined","",0);
- #endif /* SOL_SOCKET */
- return(0);
- }
- int
- sendbuf(sock,size) int sock; int size; {
- /*
- The following, from William Bader, allows changing of socket buffer sizes,
- in case that might affect performance.
- Modified by Jeff Altman to be generally useful.
- */
- #ifdef SOL_SOCKET
- #ifdef SO_SNDBUF
- int i, j;
- SOCKOPT_T x;
- #ifdef IKSD
- if (!inserver)
- #endif /* IKSD */
- if (sock == -1 ||
- nettype != NET_TCPA && nettype != NET_TCPB && nettype != NET_SSH
- || ttmdm >= 0) {
- tcp_sendbuf = size;
- return 1;
- }
- x = sizeof(i);
- if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&i, &x)) {
- debug(F111,"TCP sendbuf can't get SO_SNDBUF",ck_errstr(),errno);
- } else if (x != sizeof(i)) {
- #ifdef OS2
- short i16,j16;
- if (x == sizeof(i16)) {
- debug(F111,"TCP sendbuf warning: SO_SNDBUF","len is 16-bit",x);
- if (getsockopt(sock,
- SOL_SOCKET, SO_SNDBUF,
- (char *)&i16, &x)
- ) {
- debug(F111,"TCP sendbuf can't get SO_SNDBUF",
- ck_errstr(),errno);
- } else if (size <= 0) {
- tcp_sendbuf = i16;
- debug(F101,"TCP sendbuf SO_SNDBUF retrieved","",i16);
- return 1;
- } else if (i16 != size) {
- j16 = size;
- if (setsockopt(sock,
- SOL_SOCKET,
- SO_SNDBUF,
- (char *)&j16,
- sizeof(j16))
- ) {
- debug(F111,"TCP sendbuf can't set SO_SNDBUF",
- ck_errstr(),errno);
- } else {
- debug(F101,"TCP sendbuf old SO_SNDBUF","",i16);
- debug(F101,"TCP sendbuf new SO_SNDBUF","",j16);
- tcp_sendbuf = size;
- return 1;
- }
- } else {
- debug(F101,"TCP sendbuf SO_SNDBUF unchanged","",i16);
- tcp_sendbuf = size;
- return 1;
- }
- return(0);
- }
- #endif /* OS2 */
- debug(F111,"TCP sendbuf error: SO_SNDBUF","len",x);
- debug(F111,"TCP sendbuf SO_SNDBUF","expected len",sizeof(i));
- debug(F111,"TCP sendbuf SO_SNDBUF","i",i);
- } else if (size <= 0) {
- tcp_sendbuf = i;
- debug(F101,"TCP sendbuf SO_SNDBUF retrieved","",i);
- return 1;
- } else if (i != size) {
- j = size;
- if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&j, sizeof(j))) {
- debug(F111,"TCP sendbuf can't set SO_SNDBUF",ck_errstr(),errno);
- tcp_sendbuf = i;
- } else {
- debug(F101,"TCP sendbuf old SO_SNDBUF","",i);
- debug(F101,"TCP sendbuf new SO_SNDBUF","",j);
- tcp_sendbuf = size;
- return 1;
- }
- } else {
- debug(F101,"TCP sendbuf SO_SNDBUF unchanged","",i);
- tcp_sendbuf = size;
- return 1;
- }
- #else
- debug(F100,"TCP sendbuf SO_SNDBUF not defined","",0);
- #endif /* SO_SNDBUF */
- #else
- debug(F100,"TCP sendbuf SO_SOCKET not defined","",0);
- #endif /* SOL_SOCKET */
- return(0);
- }
- int
- recvbuf(sock,size) int sock; int size; {
- /*
- The following, from William Bader, allows changing of socket buffer sizes,
- in case that might affect performance.
- Modified by Jeff Altman to be generally useful.
- */
- #ifdef SOL_SOCKET
- #ifdef SO_RCVBUF
- int i, j;
- SOCKOPT_T x;
- #ifdef IKSD
- if (!inserver)
- #endif /* IKSD */
- if (sock == -1 ||
- nettype != NET_TCPA && nettype != NET_TCPB &&
- nettype != NET_SSH || ttmdm >= 0) {
- tcp_recvbuf = size;
- return(1);
- }
- x = sizeof(i);
- if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&i, &x)) {
- debug(F111,"TCP recvbuf can't get SO_RCVBUF",ck_errstr(),errno);
- } else if (x != sizeof(i)) {
- #ifdef OS2
- short i16,j16;
- if ( x == sizeof(i16) ) {
- debug(F111,"TCP recvbuf warning: SO_RCVBUF","len is 16-bit",x);
- if (getsockopt(sock,
- SOL_SOCKET, SO_RCVBUF,
- (char *)&i16, &x)
- ) {
- debug(F111,"TCP recvbuf can't get SO_RCVBUF",
- ck_errstr(),errno);
- } else if (size <= 0) {
- tcp_recvbuf = i16;
- debug(F101,"TCP recvbuf SO_RCVBUF retrieved","",i16);
- return 1;
- } else if (i16 != size) {
- j16 = size;
- if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&j16,
- sizeof(j16))) {
- debug(F111,"TCP recvbuf can' set SO_RCVBUF",
- ck_errstr(),errno);
- } else {
- debug(F101,"TCP recvbuf old SO_RCVBUF","",i16);
- debug(F101,"TCP recvbuf new SO_RCVBUF","",j16);
- tcp_recvbuf = size;
- return 1;
- }
- } else {
- debug(F101,"TCP recvbuf SO_RCVBUF unchanged","",i16);
- tcp_recvbuf = size;
- return 1;
- }
- return(0);
- }
- #endif /* OS2 */
- debug(F111,"TCP recvbuf error: SO_RCVBUF","len",x);
- debug(F111,"TCP recvbuf SO_RCVBUF","expected len",sizeof(i));
- debug(F111,"TCP recvbuf SO_RCVBUF","i",i);
- } else if (size <= 0) {
- tcp_recvbuf = i;
- debug(F101,"TCP recvbuf SO_RCVBUF retrieved","",i);
- return 1;
- } else if (i != size) {
- j = size;
- if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&j, sizeof(j))) {
- debug(F111,"TCP recvbuf can't set SO_RCVBUF",ck_errstr(),errno);
- tcp_recvbuf = i;
- } else {
- debug(F101,"TCP recvbuf old SO_RCVBUF","",i);
- debug(F101,"TCP recvbuf new SO_RCVBUF","",j);
- tcp_recvbuf = size;
- return 1;
- }
- } else {
- debug(F101,"TCP recvbuf SO_RCVBUF unchanged","",i);
- tcp_recvbuf = size;
- return 1;
- }
- #else
- debug(F100,"TCP recvbuf SO_RCVBUF not defined","",0);
- #endif /* SO_RCVBUF */
- #else
- debug(F100,"TCP recvbuf SO_SOCKET not defined","",0);
- #endif /* SOL_SOCKET */
- return 0;
- }
- int
- keepalive(sock,onoff) int sock; int onoff; {
- #ifdef SOL_SOCKET
- #ifdef SO_KEEPALIVE
- int get_keepalive_opt;
- int set_keepalive_opt;
- SOCKOPT_T x;
- debug(F111,"TCP keepalive","sock",sock);
- debug(F111,"TCP keepalive","nettype",nettype);
- debug(F111,"TCP keepalive","ttmdm",ttmdm);
- #ifdef IKSD
- if (!inserver)
- #endif /* IKSD */
- if (sock == -1 ||
- nettype != NET_TCPA && nettype != NET_TCPB && nettype != NET_SSH
- || ttmdm >= 0) {
- tcp_keepalive = onoff;
- return 1;
- }
- x = sizeof(get_keepalive_opt);
- if (getsockopt(sock,
- SOL_SOCKET, SO_KEEPALIVE, (char *)&get_keepalive_opt, &x)) {
- debug(F111,"TCP keepalive can't get SO_KEEPALIVE",ck_errstr(),errno);
- } else if (x != sizeof(get_keepalive_opt)) {
- #ifdef OS2
- short get_keepalive_opt16;
- short set_keepalive_opt16;
- if (x == sizeof(get_keepalive_opt16)) {
- debug(F111,"TCP keepalive warning: SO_KEEPALIVE",
- "len is 16-bit",x);
- if (getsockopt(sock,
- SOL_SOCKET, SO_KEEPALIVE,
- (char *)&get_keepalive_opt16, &x)
- ) {
- debug(F111,
- "TCP keepalive can't get SO_KEEPALIVE",
- ck_errstr(),
- errno
- );
- } else if (get_keepalive_opt16 != onoff) {
- set_keepalive_opt16 = onoff;
- if (setsockopt(sock,
- SOL_SOCKET,
- SO_KEEPALIVE,
- (char *)&set_keepalive_opt16,
- sizeof(set_keepalive_opt16))
- ) {
- debug(F111,
- "TCP keepalive can't clear SO_KEEPALIVE",
- ck_errstr(),
- errno
- );
- tcp_keepalive = get_keepalive_opt16;
- } else {
- debug(F101,
- "TCP keepalive new SO_KEEPALIVE","",
- set_keepalive_opt16);
- tcp_keepalive = set_keepalive_opt16;
- return 1;
- }
- } else {
- debug(F101,"TCP keepalive SO_KEEPALIVE unchanged","",
- get_keepalive_opt16);
- tcp_keepalive = onoff;
- return 1;
- }
- return(0);
- }
- #endif /* OS2 */
- debug(F111,"TCP keepalive error: SO_KEEPALIVE","len",x);
- debug(F111,
- "TCP keepalive SO_KEEPALIVE",
- "expected len",
- sizeof(get_keepalive_opt)
- );
- debug(F111,
- "TCP keepalive SO_KEEPALIVE",
- "keepalive_opt",
- get_keepalive_opt
- );
- } else if (get_keepalive_opt != onoff) {
- set_keepalive_opt = onoff;
- if (setsockopt(sock,
- SOL_SOCKET,
- SO_KEEPALIVE,
- (char *)&set_keepalive_opt,
- sizeof(set_keepalive_opt))
- ) {
- debug(F111,
- "TCP keepalive can't clear SO_KEEPALIVE",
- ck_errstr(),
- errno
- );
- tcp_keepalive = get_keepalive_opt;
- } else {
- debug(F101,
- "TCP keepalive new SO_KEEPALIVE",
- "",
- set_keepalive_opt
- );
- tcp_keepalive = onoff;
- return 1;
- }
- } else {
- debug(F101,"TCP keepalive SO_KEEPALIVE unchanged",
- "",
- get_keepalive_opt
- );
- tcp_keepalive = onoff;
- return 1;
- }
- #else
- debug(F100,"TCP keepalive SO_KEEPALIVE not defined","",0);
- #endif /* SO_KEEPALIVE */
- #else
- debug(F100,"TCP keepalive SO_SOCKET not defined","",0);
- #endif /* SOL_SOCKET */
- return(0);
- }
- int
- dontroute(sock,onoff) int sock; int onoff; {
- #ifdef SOL_SOCKET
- #ifdef SO_DONTROUTE
- int get_dontroute_opt;
- int set_dontroute_opt;
- SOCKOPT_T x;
- #ifdef IKSD
- if (!inserver)
- #endif /* IKSD */
- if (sock == -1 ||
- nettype != NET_TCPA && nettype != NET_TCPB && nettype != NET_SSH
- || ttmdm >= 0) {
- tcp_dontroute = onoff;
- return 1;
- }
- x = sizeof(get_dontroute_opt);
- if (getsockopt(sock,
- SOL_SOCKET, SO_DONTROUTE, (char *)&get_dontroute_opt, &x)) {
- debug(F111,"TCP dontroute can't get SO_DONTROUTE",ck_errstr(),errno);
- } else if (x != sizeof(get_dontroute_opt)) {
- #ifdef OS2
- short get_dontroute_opt16;
- short set_dontroute_opt16;
- if (x == sizeof(get_dontroute_opt16)) {
- debug(F111,"TCP dontroute warning: SO_DONTROUTE",
- "len is 16-bit",x);
- if (getsockopt(sock,
- SOL_SOCKET, SO_DONTROUTE,
- (char *)&get_dontroute_opt16, &x)
- ) {
- debug(F111,
- "TCP dontroute can't get SO_DONTROUTE",
- ck_errstr(),
- errno
- );
- } else if (get_dontroute_opt16 != onoff) {
- set_dontroute_opt16 = onoff;
- if (setsockopt(sock,
- SOL_SOCKET,
- SO_DONTROUTE,
- (char *)&set_dontroute_opt16,
- sizeof(set_dontroute_opt16))
- ) {
- debug(F111,
- "TCP dontroute can't clear SO_DONTROUTE",
- ck_errstr(),
- errno
- );
- tcp_dontroute = get_dontroute_opt16;
- } else {
- debug(F101,
- "TCP dontroute new SO_DONTROUTE","",
- set_dontroute_opt16);
- tcp_dontroute = set_dontroute_opt16;
- return 1;
- }
- } else {
- debug(F101,"TCP dontroute SO_DONTROUTE unchanged","",
- get_dontroute_opt16);
- tcp_dontroute = onoff;
- return 1;
- }
- return(0);
- }
- #endif /* OS2 */
- debug(F111,"TCP dontroute error: SO_DONTROUTE","len",x);
- debug(F111,
- "TCP dontroute SO_DONTROUTE",
- "expected len",
- sizeof(get_dontroute_opt)
- );
- debug(F111,
- "TCP dontroute SO_DONTROUTE",
- "dontroute_opt",
- get_dontroute_opt
- );
- } else if (get_dontroute_opt != onoff) {
- set_dontroute_opt = onoff;
- if (setsockopt(sock,
- SOL_SOCKET,
- SO_DONTROUTE,
- (char *)&set_dontroute_opt,
- sizeof(set_dontroute_opt))
- ) {
- debug(F111,
- "TCP dontroute can't clear SO_DONTROUTE",
- ck_errstr(),
- errno
- );
- tcp_dontroute = get_dontroute_opt;
- } else {
- debug(F101,
- "TCP dontroute new SO_DONTROUTE",
- "",
- set_dontroute_opt
- );
- tcp_dontroute = onoff;
- return 1;
- }
- } else {
- debug(F101,"TCP dontroute SO_DONTROUTE unchanged",
- "",
- get_dontroute_opt
- );
- tcp_dontroute = onoff;
- return 1;
- }
- #else
- debug(F100,"TCP dontroute SO_DONTROUTE not defined","",0);
- #endif /* SO_DONTROUTE */
- #else
- debug(F100,"TCP dontroute SO_SOCKET not defined","",0);
- #endif /* SOL_SOCKET */
- return(0);
- }
- int
- no_delay(sock,onoff) int sock; int onoff; {
- #ifdef SOL_SOCKET
- #ifdef TCP_NODELAY
- int get_nodelay_opt;
- int set_nodelay_opt;
- SOCKOPT_T x;
- #ifdef IKSD
- if (!inserver)
- #endif /* IKSD */
- if (sock == -1 ||
- nettype != NET_TCPA && nettype != NET_TCPB && nettype != NET_SSH
- || ttmdm >= 0) {
- tcp_nodelay = onoff;
- return(1);
- }
- x = sizeof(get_nodelay_opt);
- if (getsockopt(sock,IPPROTO_TCP,TCP_NODELAY,
- (char *)&get_nodelay_opt,&x)) {
- debug(F111,
- "TCP no_delay can't get TCP_NODELAY",
- ck_errstr(),
- errno);
- } else if (x != sizeof(get_nodelay_opt)) {
- #ifdef OS2
- short get_nodelay_opt16;
- short set_nodelay_opt16;
- if (x == sizeof(get_nodelay_opt16)) {
- debug(F111,"TCP no_delay warning: TCP_NODELAY","len is 16-bit",x);
- if (getsockopt(sock,
- IPPROTO_TCP, TCP_NODELAY,
- (char *)&get_nodelay_opt16, &x)
- ) {
- debug(F111,
- "TCP no_delay can't get TCP_NODELAY",
- ck_errstr(),
- errno);
- } else if (get_nodelay_opt16 != onoff) {
- set_nodelay_opt16 = onoff;
- if (setsockopt(sock,
- IPPROTO_TCP,
- TCP_NODELAY,
- (char *)&set_nodelay_opt16,
- sizeof(set_nodelay_opt16))
- ) {
- debug(F111,
- "TCP no_delay can't clear TCP_NODELAY",
- ck_errstr(),
- errno);
- tcp_nodelay = get_nodelay_opt16;
- } else {
- debug(F101,
- "TCP no_delay new TCP_NODELAY",
- "",
- set_nodelay_opt16);
- tcp_nodelay = onoff;
- return 1;
- }
- } else {
- debug(F101,"TCP no_delay TCP_NODELAY unchanged","",
- get_nodelay_opt16);
- tcp_nodelay = onoff;
- return 1;
- }
- return(0);
- }
- #endif /* OS2 */
- debug(F111,"TCP no_delay error: TCP_NODELAY","len",x);
- debug(F111,"TCP no_delay TCP_NODELAY","expected len",
- sizeof(get_nodelay_opt));
- debug(F111,"TCP no_delay TCP_NODELAY","nodelay_opt",get_nodelay_opt);
- } else if (get_nodelay_opt != onoff) {
- set_nodelay_opt = onoff;
- if (setsockopt(sock,
- IPPROTO_TCP,
- TCP_NODELAY,
- (char *)&set_nodelay_opt,
- sizeof(set_nodelay_opt))) {
- debug(F111,
- "TCP no_delay can't clear TCP_NODELAY",
- ck_errstr(),
- errno
- );
- tcp_nodelay = get_nodelay_opt;
- } else {
- debug(F101,"TCP no_delay new TCP_NODELAY","",set_nodelay_opt);
- tcp_nodelay = onoff;
- return 1;
- }
- } else {
- debug(F101,"TCP no_delay TCP_NODELAY unchanged","",get_nodelay_opt);
- tcp_nodelay = onoff;
- return(1);
- }
- #else
- debug(F100,"TCP no_delay TCP_NODELAY not defined","",0);
- #endif /* TCP_NODELAY */
- #else
- debug(F100,"TCP no_delay SO_SOCKET not defined","",0);
- #endif /* SOL_SOCKET */
- return 0;
- }
- #endif /* datageneral */
- #endif /* NOTCPOPTS */
- #ifdef SUNX25
- #ifndef X25_WR_FACILITY
- /* For Solaris 2.3 / SunLink 8.x - see comments in ckcnet.h */
- void
- bzero(s,n) char *s; int n; {
- memset(s,0,n);
- }
- #endif /* X25_WR_FACILITY */
- #endif /* SUNX25 */
- #ifdef TCPSOCKET
- #ifndef OS2
- #ifndef NOLISTEN
- #ifdef BSDSELECT
- #ifndef VMS
- #ifndef BELLV10
- #ifndef datageneral
- #ifdef hp9000s500 /* HP-9000/500 HP-U 5.21 */
- #include <time.h>
- #else
- /****** THIS SECTION ADDED BY STEVE RANCE - OS9 NETWORK SERVER
- * ------------------------------------------------------
- *
- * Due to OS9's Lack of a select() call, the following seems to be
- * enough to fool the rest of the code into compiling. The only
- * effect that I can see is using control L to refresh the status
- * display gets qued up until some network packets arrive.
- *
- * This solution is by no means elegant but works enough to be
- * a (the) solution.
- *
- * Also with the defines I had specified in my makefile I had to
- * have an #endif right at the end of the file when compiling.
- * I did not bother speding time to find out why.
- *
- * COPTS = -to=osk -d=OSK -d=TCPSOCKET -d=SELECT -d=VOID=void -d=SIG_V \
- * -d=DYNAMIC -d=PARSENSE -d=KANJI -d=MYCURSES -d=ZFCDAT \
- * -d=CK_APC -d=CK_REDIR -d=RENAME -d=CK_TTYFD -d=NOOLDMODEMS \
- * -d=CK_ANSIC -d=CK_XYZ -tp=68040d -l=netdb.l -l=socklib.l \
- * -l=termlib.l -l=math.l -l=sys_clib.l
- *
- * stever@ozemail.com.au
- */
- #ifdef OSK
- #define BSDSELECT /* switch on BSD select code */
- #define FD_SETSIZE 32 /* Max # of paths in OS9 */
- #define FD_ZERO(p) ((*p)=0)
- #define FD_SET(n,b) ((*b)|=(1<<(n)))
- #define FD_ISSET(n,b) 1 /* always say data is ready */
- #define select(a,b,c,d,e) 1 /* always say 1 path has data */
- typedef int fd_set; /* keep BSD Code Happy */
- struct timeval {int tv_sec,tv_usec;}; /* keep BSD Code Happy */
- /****** END OF OS9 MODS FROM STEVE RANCE **************************/
- #endif /* OSK */
- #include <sys/time.h>
- #endif /* hp9000s500 */
- #endif /* datageneral */
- #endif /* BELLV10 */
- #endif /* VMS */
- #ifdef SELECT_H
- #include <sys/select.h>
- #endif /* SELECT_H */
- #endif /* BSDSELECT */
- #ifdef SELECT
- #ifdef CK_SCOV5
- #include <sys/select.h>
- #endif /* CK_SCOV5 */
- #endif /* SELECT */
- #ifdef NOTUSED
- /* T C P S O C K E T _ O P E N -- Open a preexisting socket number */
- int
- tcpsocket_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo {
- int on = 1;
- static struct servent *service, servrec;
- static struct hostent *host;
- static struct sockaddr_in saddr;
- static
- #ifdef UCX50
- unsigned
- #endif /* UCX50 */
- int saddrlen;
- #ifdef BSDSELECT
- fd_set rfds;
- struct timeval tv;
- #else
- #ifdef BELLSELECT
- fd_set rfds;
- #else
- fd_set rfds;
- fd_set rfds;
- struct timeval {
- long tv_sec;
- long tv_usec;
- } tv;
- #endif /* BELLSELECT */
- #endif /* BSDSELECT */
- debug(F101,"tcpsocket_open nett","",nett);
- *ipaddr = '\0';
- if (nett != NET_TCPB)
- return(-1); /* BSD socket support */
- netclos(); /* Close any previous connection. */
- ckstrncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
- #ifdef COMMENT
- /* Jeff's version from 30 Dec 2005 doesn't inhibit Telnet */
- if (ttnproto != NP_TCPRAW &&
- ttnproto != NP_SSL_RAW &&
- ttnproto != NP_TLS_RAW)
- ttnproto = NP_NONE; /* No protocol selected yet. */
- #else
- /* fdc's version from 4 Dec 2005 works ok */
- if (ttnproto != NP_TCPRAW)
- ttnproto = NP_NONE; /* No protocol selected yet. */
- #endif /* COMMENT */
- debug(F110,"tcpsocket_open namecopy",namecopy,0);
- /* Assign the socket number to ttyfd and then fill in tcp structures */
- ttyfd = atoi(&name[1]);
- debug(F111,"tcpsocket_open","ttyfd",ttyfd);
- #ifndef NOTCPOPTS
- #ifdef SOL_SOCKET
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #ifndef datageneral
- #ifdef TCP_NODELAY
- no_delay(ttyfd,tcp_nodelay);
- #endif /* TCP_NODELAY */
- #ifdef SO_KEEPALIVE
- keepalive(ttyfd,tcp_keepalive);
- #endif /* SO_KEEPALIVE */
- #ifdef SO_LINGER
- ck_linger(ttyfd,tcp_linger, tcp_linger_tmo);
- #endif /* SO_LINGER */
- #ifdef SO_SNDBUF
- sendbuf(ttyfd,tcp_sendbuf);
- #endif /* SO_SNDBUF */
- #ifdef SO_RCVBUF
- recvbuf(ttyfd,tcp_recvbuf);
- #endif /* SO_RCVBUF */
- #endif /* datageneral */
- #endif /* SOL_SOCKET */
- #endif /* NOTCPOPTS */
- #ifdef NT_TCP_OVERLAPPED
- OverlappedWriteInit();
- OverlappedReadInit();
- #endif /* NT_TCP_OVERLAPPED */
- /* Get the name of the host we are connected to */
- saddrlen = sizeof(saddr);
- getpeername(ttyfd,(struct sockaddr *)&saddr,&saddrlen);
- ckstrncpy(ipaddr,(char *)inet_ntoa(saddr.sin_addr),20);
- if (tcp_rdns == SET_ON
- #ifdef CK_KERBEROS
- || tcp_rdns == SET_AUTO &&
- (ck_krb5_is_installed() || ck_krb4_is_installed())
- #endif /* CK_KERBEROS */
- #ifndef NOHTTP
- && (tcp_http_proxy == NULL)
- #endif /* NOHTTP */
- #ifdef CK_SSL
- && !(ssl_only_flag || tls_only_flag)
- #endif /* CK_SSL */
- ) { /* Reverse DNS */
- if (!quiet) {
- printf(" Reverse DNS Lookup... ");
- fflush(stdout);
- }
- host = gethostbyaddr((char *)&saddr.sin_addr,4,PF_INET);
- debug(F110,"tcpsocket_open gethostbyaddr",host ? "OK" : "FAILED",0);
- if (host) {
- host = ck_copyhostent(host);
- debug(F100,"tcpsocket_open gethostbyaddr != NULL","",0);
- if (!quiet) {
- printf("(OK)\n");
- fflush(stdout);
- }
- ckstrncpy(name, host->h_name, 80);
- ckstrncat(name, ":", 80);
- ckstrncat(name,ckuitoa(ntohs(saddr.sin_port)), 80);
- if (!quiet
- #ifndef NOICP
- && !doconx
- #endif /* NOICP */
- )
- printf("%s connected on port %d\n",
- host->h_name,
- ntohs(saddr.sin_port)
- );
- } else if (!quiet)
- printf("Failed\n");
- } else if (!quiet)
- printf("(OK)\n");
- if (tcp_rdns != SET_ON || !host) {
- ckstrncpy(name,ipaddr,80);
- ckstrncat(name,":",80);
- ckstrncat(name,ckuitoa(ntohs(saddr.sin_port)),80);
- if (!quiet
- #ifdef NOICP
- && !doconx
- #endif /* NOICP */
- )
- printf("%s connected on port %d\n",ipaddr,ntohs(saddr.sin_port));
- }
- if (!quiet) fflush(stdout);
- ttnet = nett; /* TCP/IP (sockets) network */
- #ifdef RLOGCODE
- if (ntohs(saddr.sin_port) == 513)
- ttnproto = NP_LOGIN;
- else
- #endif /* RLOGCODE */
- /* Assume the service is TELNET. */
- #ifdef COMMENT
- /* Jeff's code from 2005/12/30 */
- if (ttnproto != NP_TCP_RAW &&
- ttnproto != NP_SSL_RAW &&
- ttnproto != NP_TLS_RAW)
- #else
- /* fdc's code from 2005/12/04 */
- if (ttnproto != NP_TCPRAW)
- #endif /* COMMENT */
- ttnproto = NP_TELNET; /* Yes, set global flag. */
- #ifdef CK_SECURITY
- /* Before Initialization Telnet/Rlogin Negotiations Init Kerberos */
- ck_auth_init((tcp_rdns && host && host->h_name && host->h_name[0]) ?
- host->h_name : ipaddr,
- ipaddr,
- uidbuf,
- ttyfd
- );
- #endif /* CK_SECURITY */
- if (tn_ini() < 0) /* Start/Reset TELNET negotiations */
- if (ttchk() < 0) /* Did it fail due to connect loss? */
- return(-1);
- if (*lcl < 0) *lcl = 1; /* Local mode. */
- return(0); /* Done. */
- }
- #endif /* NOTUSED */
- /* T C P S R V _ O P E N -- Open a TCP/IP Server connection */
- /*
- Calling conventions same as ttopen(), except third argument is network
- type rather than modem type.
- */
- int
- tcpsrv_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo; {
- char *p;
- int i, x;
- SOCKOPT_T on = 1;
- int ready_to_accept = 0;
- static struct servent *service, *service2, servrec;
- static struct hostent *host;
- static struct sockaddr_in saddr;
- struct sockaddr_in l_addr;
- GSOCKNAME_T l_slen;
- #ifdef UCX50
- static u_int saddrlen;
- #else
- static SOCKOPT_T saddrlen;
- #endif /* UCX50 */
- #ifdef BSDSELECT
- fd_set rfds;
- struct timeval tv;
- #else
- #ifdef BELLSELCT
- fd_set rfds;
- #else
- fd_set rfds;
- struct timeval {
- long tv_sec;
- long tv_usec;
- } tv;
- #endif /* BELLSELECT */
- #endif /* BSDSELECT */
- #ifdef CK_SSL
- int ssl_failed = 0;
- #endif /* CK_SSL */
- debug(F101,"tcpsrv_open nett","",nett);
- *ipaddr = '\0';
- if (nett != NET_TCPB)
- return(-1); /* BSD socket support */
- netclos(); /* Close any previous connection. */
- ckstrncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
- /* Don't do this. */
- #ifdef COMMENT
- /* fdc */
- if (ttnproto != NP_TCPRAW)
- ttnproto = NP_NONE; /* No protocol selected yet. */
- #endif /* COMMENT */
- #ifdef COMMENT
- /* Jeff */
- if (ttnproto != NP_TCP_RAW &&
- ttnproto != NP_SSL_RAW &&
- ttnproto != NP_TLS_RAW)
- ttnproto = NP_NONE; /* No protocol selected yet. */
- #endif /* COMMENT */
- debug(F110,"tcpsrv_open namecopy",namecopy,0);
- p = namecopy; /* Was a service requested? */
- while (*p != '\0' && *p != ':')
- p++; /* Look for colon */
- if (*p == ':') { /* Have a colon */
- *p++ = '\0'; /* Get service name or number */
- } else { /* Otherwise use kermit */
- p = "kermit";
- }
- debug(F110,"tcpsrv_open service requested",p,0);
- if (isdigit(*p)) { /* Use socket number without lookup */
- service = &servrec;
- service->s_port = htons((unsigned short)atoi(p));
- } else { /* Otherwise lookup the service name */
- service = getservbyname(p, "tcp");
- }
- if (!service && !strcmp("kermit",p)) { /* Use Kermit service port */
- service = &servrec;
- service->s_port = htons(1649);
- }
- #ifdef RLOGCODE
- if (service && !strcmp("login",p) && service->s_port != htons(513)) {
- fprintf(stderr,
- " Warning: login service on port %d instead of port 513\n",
- ntohs(service->s_port));
- fprintf(stderr, " Edit SERVICES file if RLOGIN fails to connect.\n");
- debug(F101,"tcpsrv_open login on port","",ntohs(service->s_port));
- }
- #endif /* RLOGCODE */
- if (!service) {
- fprintf(stderr, "Cannot find port for service: %s\n", p);
- debug(F111,"tcpsrv_open can't get service",p,errno);
- errno = 0; /* rather than mislead */
- return(-1);
- }
- /* If we currently have a listen active but port has changed then close */
- debug(F101,"tcpsrv_open checking previous connection","",tcpsrfd);
- debug(F101,"tcpsrv_open previous tcpsrv_port","",tcpsrv_port);
- if (tcpsrfd != -1 &&
- tcpsrv_port != ntohs((unsigned short)service->s_port)) {
- debug(F100,"tcpsrv_open closing previous connection","",0);
- #ifdef TCPIPLIB
- socket_close(tcpsrfd);
- #else
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- tcpsrfd = -1;
- }
- debug(F100,"tcpsrv_open tcpsrfd","",tcpsrfd);
- if (tcpsrfd == -1) {
- /* Set up socket structure and get host address */
- bzero((char *)&saddr, sizeof(saddr));
- debug(F100,"tcpsrv_open bzero ok","",0);
- saddr.sin_family = AF_INET;
- if (tcp_address) {
- #ifdef INADDRX
- inaddrx = inet_addr(tcp_address);
- saddr.sin_addr.s_addr = *(unsigned long *)&inaddrx;
- #else
- saddr.sin_addr.s_addr = inet_addr(tcp_address);
- #endif /* INADDRX */
- } else
- saddr.sin_addr.s_addr = INADDR_ANY;
- /* Get a file descriptor for the connection. */
- saddr.sin_port = service->s_port;
- ipaddr[0] = '\0';
- debug(F100,"tcpsrv_open calling socket","",0);
- if ((tcpsrfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("TCP socket error");
- debug(F101,"tcpsrv_open socket error","",errno);
- return (-1);
- }
- errno = 0;
- /* Specify the Port may be reused */
- debug(F100,"tcpsrv_open calling setsockopt","",0);
- x = setsockopt(tcpsrfd,
- SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof on);
- debug(F101,"tcpsrv_open setsockopt","",x);
- /* Now bind to the socket */
- printf("\nBinding socket to port %d ...\n",
- ntohs((unsigned short)service->s_port));
- if (bind(tcpsrfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
- i = errno; /* Save error code */
- #ifdef TCPIPLIB
- socket_close(tcpsrfd);
- #else /* TCPIPLIB */
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- tcpsrfd = -1;
- tcpsrv_port = 0;
- ttyfd = -1;
- wasclosed = 1;
- errno = i; /* and report this error */
- debug(F101,"tcpsrv_open bind errno","",errno);
- printf("?Unable to bind to socket (errno = %d)\n",errno);
- return(-1);
- }
- debug(F100,"tcpsrv_open bind OK","",0);
- printf("Listening ...\n");
- if (listen(tcpsrfd, 15) < 0) {
- i = errno; /* Save error code */
- #ifdef TCPIPLIB
- socket_close(tcpsrfd);
- #else /* TCPIPLIB */
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- tcpsrfd = -1;
- tcpsrv_port = 0;
- ttyfd = -1;
- wasclosed = 1;
- errno = i; /* And report this error */
- debug(F101,"tcpsrv_open listen errno","",errno);
- return(-1);
- }
- debug(F100,"tcpsrv_open listen OK","",0);
- tcpsrv_port = ntohs((unsigned short)service->s_port);
- }
- #ifdef CK_SSL
- if (ck_ssleay_is_installed()) {
- if (!ssl_tn_init(SSL_SERVER)) {
- ssl_failed = 1;
- if (bio_err!=NULL) {
- BIO_printf(bio_err,"do_ssleay_init() failed\n");
- ERR_print_errors(bio_err);
- } else {
- fflush(stderr);
- fprintf(stderr,"do_ssleay_init() failed\n");
- ERR_print_errors_fp(stderr);
- }
- if (tls_only_flag || ssl_only_flag) {
- #ifdef TCPIPLIB
- socket_close(ttyfd);
- socket_close(tcpsrfd);
- #else /* TCPIPLIB */
- close(ttyfd);
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- ttyfd = -1;
- wasclosed = 1;
- tcpsrfd = -1;
- tcpsrv_port = 0;
- return(-1);
- }
- /* we will continue to accept the connection */
- /* without SSL or TLS support unless required. */
- if ( TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) != TN_NG_MU )
- TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
- if ( TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) != TN_NG_MU )
- TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
- if ( TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) != TN_NG_MU )
- TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
- if ( TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) != TN_NG_MU )
- TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
- }
- }
- #endif /* CK_SSL */
- printf("\nWaiting to Accept a TCP/IP connection on port %d ...\n",
- ntohs((unsigned short)service->s_port));
- saddrlen = sizeof(saddr);
- #ifdef BSDSELECT
- tv.tv_sec = tv.tv_usec = 0L;
- if (timo < 0)
- tv.tv_usec = (long) -timo * 10000L;
- else
- tv.tv_sec = timo;
- debug(F101,"tcpsrv_open BSDSELECT","",timo);
- #else
- debug(F101,"tcpsrv_open not BSDSELECT","",timo);
- #endif /* BSDSELECT */
- if (timo) {
- while (!ready_to_accept) {
- #ifdef BSDSELECT
- FD_ZERO(&rfds);
- FD_SET(tcpsrfd, &rfds);
- ready_to_accept =
- ((select(FD_SETSIZE,
- #ifdef HPUX
- #ifdef HPUX1010
- (fd_set *)
- #else
- (int *)
- #endif /* HPUX1010 */
- #else
- #ifdef __DECC
- #ifdef INTSELECT
- (int *)
- #else /* def INTSELECT */
- (fd_set *)
- #endif /* def INTSELECT [else] */
- #endif /* __DECC */
- #endif /* HPUX */
- &rfds, NULL, NULL, &tv) > 0) &&
- FD_ISSET(tcpsrfd, &rfds));
- #else /* BSDSELECT */
- #ifdef IBMSELECT
- #define ck_sleepint 250
- ready_to_accept =
- (select(&tcpsrfd, 1, 0, 0,
- timo < 0 ? -timo :
- (timo > 0 ? timo * 1000L : ck_sleepint)) == 1
- );
- #else
- #ifdef BELLSELECT
- FD_ZERO(rfds);
- FD_SET(tcpsrfd, rfds);
- ready_to_accept =
- ((select(128, rfds, NULL, NULL, timo < 0 ? -timo :
- (timo > 0 ? timo * 1000L)) > 0) &&
- FD_ISSET(tcpsrfd, rfds));
- #else
- /* Try this - what's the worst that can happen... */
- FD_ZERO(&rfds);
- FD_SET(tcpsrfd, &rfds);
- ready_to_accept =
- ((select(FD_SETSIZE,
- (fd_set *) &rfds, NULL, NULL, &tv) > 0) &&
- FD_ISSET(tcpsrfd, &rfds));
- #endif /* BELLSELECT */
- #endif /* IBMSELECT */
- #endif /* BSDSELECT */
- }
- }
- if (ready_to_accept || timo == 0) {
- if ((ttyfd = accept(tcpsrfd,
- (struct sockaddr *)&saddr,&saddrlen)) < 0) {
- i = errno; /* save error code */
- #ifdef TCPIPLIB
- socket_close(tcpsrfd);
- #else /* TCPIPLIB */
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- ttyfd = -1;
- wasclosed = 1;
- tcpsrfd = -1;
- tcpsrv_port = 0;
- errno = i; /* and report this error */
- debug(F101,"tcpsrv_open accept errno","",errno);
- return(-1);
- }
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #ifndef NOTCPOPTS
- #ifndef datageneral
- #ifdef SOL_SOCKET
- #ifdef TCP_NODELAY
- no_delay(ttyfd,tcp_nodelay);
- debug(F101,"tcpsrv_open no_delay","",tcp_nodelay);
- #endif /* TCP_NODELAY */
- #ifdef SO_KEEPALIVE
- keepalive(ttyfd,tcp_keepalive);
- debug(F101,"tcpsrv_open keepalive","",tcp_keepalive);
- #endif /* SO_KEEPALIVE */
- #ifdef SO_LINGER
- ck_linger(ttyfd,tcp_linger, tcp_linger_tmo);
- debug(F101,"tcpsrv_open linger","",tcp_linger_tmo);
- #endif /* SO_LINGER */
- #ifdef SO_SNDBUF
- sendbuf(ttyfd,tcp_sendbuf);
- #endif /* SO_SNDBUF */
- #ifdef SO_RCVBUF
- recvbuf(ttyfd,tcp_recvbuf);
- #endif /* SO_RCVBUF */
- #endif /* SOL_SOCKET */
- #endif /* datageneral */
- #endif /* NOTCPOPTS */
- ttnet = nett; /* TCP/IP (sockets) network */
- tcp_incoming = 1; /* This is an incoming connection */
- sstelnet = 1; /* Do server-side Telnet protocol */
- /* See if the service is TELNET. */
- x = (unsigned short)service->s_port;
- service2 = getservbyname("telnet", "tcp");
- if (service2 && x == service2->s_port) {
- #ifdef COMMENT
- /* Jeff 2005/12/30 */
- if (ttnproto != NP_TCPRAW && /* Yes... */
- ttnproto != NP_SSL_RAW &&
- ttnproto != NP_TLS_RAW) /* and if raw port not requested */
- #else
- /* fdc 2005/12/04 */
- if (ttnproto != NP_TCPRAW) /* Yes and if raw port not requested */
- #endif /* */
- ttnproto = NP_TELNET; /* set protocol to TELNET. */
- }
- ckstrncpy(ipaddr,(char *)inet_ntoa(saddr.sin_addr),20);
- if (tcp_rdns) {
- if (!quiet) {
- printf(" Reverse DNS Lookup... ");
- fflush(stdout);
- }
- if (host = gethostbyaddr((char *)&saddr.sin_addr,4,PF_INET)) {
- host = ck_copyhostent(host);
- debug(F100,"tcpsrv_open gethostbyaddr != NULL","",0);
- if (!quiet) {
- printf("(OK)\n");
- fflush(stdout);
- }
- name[0] = '*';
- ckstrncpy(&name[1],host->h_name,78);
- ckstrncat(name,":",80-strlen(name));
- ckstrncat(name,p,80-strlen(name));
- if (!quiet
- #ifndef NOICP
- && !doconx
- #endif /* NOICP */
- )
- printf("%s connected on port %s\n",host->h_name,p);
- } else {
- if (!quiet) printf("Failed.\n");
- }
- } else if (!quiet) printf("(OK)\n");
- if (!tcp_rdns || !host) {
- ckstrncpy(name,ipaddr,80);
- ckstrncat(name,":",80);
- ckstrncat(name,ckuitoa(ntohs(saddr.sin_port)),80);
- if (!quiet
- #ifndef NOICP
- && !doconx
- #endif /* NOICP */
- )
- printf("%s connected on port %d\n",ipaddr,ntohs(saddr.sin_port));
- }
- if (!quiet) fflush(stdout);
- #ifdef CK_SECURITY
- /* Before Initialization Telnet/Rlogin Negotiations Init Kerberos */
- ck_auth_init((tcp_rdns && host && host->h_name && host->h_name[0]) ?
- (char *)host->h_name : ipaddr,
- ipaddr,
- uidbuf,
- ttyfd
- );
- #endif /* CK_SECURITY */
- #ifdef CK_SSL
- if (ck_ssleay_is_installed() && !ssl_failed) {
- if (ck_ssl_incoming(ttyfd) < 0) {
- #ifdef TCPIPLIB
- socket_close(ttyfd);
- socket_close(tcpsrfd);
- #else /* TCPIPLIB */
- close(ttyfd);
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- ttyfd = -1;
- wasclosed = 1;
- tcpsrfd = -1;
- tcpsrv_port = 0;
- return(-1);
- }
- }
- #endif /* CK_SSL */
- #ifndef datageneral
- /* Find out our own IP address. */
- l_slen = sizeof(l_addr);
- bzero((char *)&l_addr, l_slen);
- #ifndef EXCELAN
- if (!getsockname(ttyfd, (struct sockaddr *)&l_addr, &l_slen)) {
- char * s = (char *)inet_ntoa(l_addr.sin_addr);
- ckstrncpy(myipaddr, s,20);
- debug(F110,"getsockname",myipaddr,0);
- }
- #endif /* EXCELAN */
- #endif /* datageneral */
- if (tn_ini() < 0) /* Start TELNET negotiations. */
- if (ttchk() < 0) { /* Disconnected? */
- i = errno; /* save error code */
- #ifdef TCPIPLIB
- socket_close(tcpsrfd);
- #else /* TCPIPLIB */
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- ttyfd = -1;
- wasclosed = 1;
- tcpsrfd = -1;
- tcpsrv_port = 0;
- errno = i; /* and report this error */
- debug(F101,"tcpsrv_open accept errno","",errno);
- return(-1);
- }
- debug(F101,"tcpsrv_open service","",x);
- if (*lcl < 0) /* Set local mode. */
- *lcl = 1;
- #ifdef CK_KERBEROS
- #ifdef KRB5_U2U
- if ( ttnproto == NP_K5U2U ) {
- if (k5_user_to_user_server_auth() != 0) {
- i = errno; /* save error code */
- #ifdef TCPIPLIB
- socket_close(tcpsrfd);
- #else /* TCPIPLIB */
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- ttyfd = -1;
- wasclosed = 1;
- tcpsrfd = -1;
- tcpsrv_port = 0;
- errno = i; /* and report this error */
- debug(F101,"tcpsrv_open accept errno","",errno);
- return(-1);
- }
- }
- #endif /* KRB5_U2U */
- #endif /* CK_KERBEROS */
- return(0); /* Done. */
- } else {
- i = errno; /* save error code */
- #ifdef TCPIPLIB
- socket_close(tcpsrfd);
- #else /* TCPIPLIB */
- close(tcpsrfd);
- #endif /* TCPIPLIB */
- ttyfd = -1;
- wasclosed = 1;
- tcpsrfd = -1;
- tcpsrv_port = 0;
- errno = i; /* and report this error */
- debug(F101,"tcpsrv_open accept errno","",errno);
- return(-1);
- }
- }
- #endif /* NOLISTEN */
- #endif /* OS2 */
- #endif /* TCPSOCKET */
- #endif /* NONET */
- #ifdef TCPSOCKET
- char *
- ckname2addr(name) char * name;
- {
- #ifdef HPUX5
- return("");
- #else
- struct hostent *host;
- if (name == NULL || *name == '\0')
- return("");
- host = gethostbyname(name);
- if ( host ) {
- host = ck_copyhostent(host);
- return(inet_ntoa(*((struct in_addr *) host->h_addr)));
- }
- return("");
- #endif /* HPUX5 */
- }
- char *
- ckaddr2name(addr) char * addr;
- {
- #ifdef HPUX5
- return("");
- #else
- struct hostent *host;
- struct in_addr sin_addr;
- if (addr == NULL || *addr == '\0')
- return("");
- sin_addr.s_addr = inet_addr(addr);
- host = gethostbyaddr((char *)&sin_addr,4,AF_INET);
- if (host) {
- host = ck_copyhostent(host);
- return((char *)host->h_name);
- }
- return("");
- #endif /* HPUX5 */
- }
- #endif /* TCPSOCKET */
- unsigned long peerxipaddr = 0L;
- char *
- ckgetpeer() {
- #ifdef TCPSOCKET
- static char namebuf[256];
- static struct hostent *host;
- static struct sockaddr_in saddr;
- #ifdef GPEERNAME_T
- static GPEERNAME_T saddrlen;
- #else
- #ifdef PTX
- static size_t saddrlen;
- #else
- #ifdef AIX42
- /* It's size_t in 4.2 but int in 4.1 and earlier. */
- /* Note: the 4.2 man page lies; believe socket.h. */
- static size_t saddrlen;
- #else
- #ifdef UNIXWARE
- static size_t saddrlen;
- #else /* UNIXWARE */
- #ifdef DEC_TCPIP
- /* 2010-03-08 SMS.
- * Coincidentally, the condition for integer arguments in select(),
- * which is actually "defined( _DECC_V4_SOURCE)", works for an integer
- * argument in getpeername(). Sadly, due to a lack of foresight,
- * "defined( _DECC_V4_SOURCE)" doesn't work with DEC C V4.0, so the
- * user-specified INTSELECT is used instead. Most likely, "size_t"
- * should be used instead of "unsigned int", but I'm a coward.
- */
- #ifdef INTSELECT
- static int saddrlen;
- #else /* def INTSELECT */
- static unsigned int saddrlen;
- #endif /* def INTSELECT [else] */
- #else
- #ifdef MACOSX10
- static unsigned int saddrlen;
- #else
- #ifdef CK_64BIT
- static socklen_t saddrlen;
- #else
- static int saddrlen;
- #endif /* CK_64BIT */
- #endif /* MACOSX10 */
- #endif /* DEC_TCPIP */
- #endif /* UNIXWARE */
- #endif /* AIX42 */
- #endif /* PTX */
- #endif /* GPEERNAME_T */
- saddrlen = sizeof(saddr);
- if (getpeername(ttyfd,(struct sockaddr *)&saddr,&saddrlen) < 0) {
- debug(F111,"ckgetpeer failure",ckitoa(ttyfd),errno);
- return(NULL);
- }
- host = gethostbyaddr((char *)&saddr.sin_addr,4,AF_INET);
- if (host) {
- host = ck_copyhostent(host);
- ckstrncpy(namebuf,(char *)host->h_name,80);
- } else {
- ckstrncpy(namebuf,(char *)inet_ntoa(saddr.sin_addr),80);
- }
- peerxipaddr = ntohl(saddr.sin_addr.s_addr);
- debug(F111,"ckgetpeer",namebuf,peerxipaddr);
- return(namebuf);
- #else
- return(NULL);
- #endif /* TCPSOCKET */
- }
- /* Get fully qualified IP hostname */
- #ifndef NONET
- char *
- #ifdef CK_ANSIC
- ckgetfqhostname(char * name)
- #else
- ckgetfqhostname(name) char * name;
- #endif /* CK_ANSIC */
- {
- #ifdef NOCKGETFQHOST
- return(name);
- #else /* If the following code dumps core, define NOCKGETFQHOST and rebuild. */
- static char namebuf[256];
- struct hostent *host=NULL;
- struct sockaddr_in r_addr;
- int i;
- debug(F110,"ckgetfqhn()",name,0);
- ckstrncpy(namebuf,name,256);
- namebuf[255] = '\0';
- i = ckindex(":",namebuf,0,0,0);
- if (i)
- namebuf[i-1] = '\0';
- bzero((char *)&r_addr, sizeof(r_addr));
- host = gethostbyname(namebuf);
- if (host) {
- host = ck_copyhostent(host);
- debug(F100,"ckgetfqhn() gethostbyname != NULL","",0);
- r_addr.sin_family = host->h_addrtype;
- #ifdef HADDRLIST
- #ifdef h_addr
- /* This is for trying multiple IP addresses - see <netdb.h> */
- if (!(host->h_addr_list))
- goto exit_func;
- bcopy(host->h_addr_list[0],
- (caddr_t)&r_addr.sin_addr,
- host->h_length
- );
- #else
- bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
- #endif /* h_addr */
- #else /* HADDRLIST */
- bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
- #endif /* HADDRLIST */
- #ifdef COMMENT
- #ifndef EXCELAN
- debug(F111,"BCOPY","host->h_addr",host->h_addr);
- #endif /* EXCELAN */
- debug(F111,"BCOPY"," (caddr_t)&r_addr.sin_addr",
- (caddr_t)&r_addr.sin_addr);
- #endif /* COMMENT */
- debug(F111,"BCOPY","host->h_length",host->h_length);
- #ifdef NT
- /* Windows 95/98 requires a 1 second wait between calls to Microsoft */
- /* provided DNS functions. Otherwise, the TTL of the DNS response */
- /* is ignored. */
- if (isWin95())
- sleep(1);
- #endif /* NT */
- host = gethostbyaddr((char *)&r_addr.sin_addr,4,PF_INET);
- if (host) {
- host = ck_copyhostent(host);
- debug(F100,"ckgetfqhn() gethostbyaddr != NULL","",0);
- ckstrncpy(namebuf, host->h_name, 256);
- }
- }
- #ifdef HADDRLIST
- #ifdef h_addr
- exit_func:
- #endif /* h_addr */
- #endif /* HADDRLIST */
- if (i > 0)
- ckstrncat(namebuf,&name[i-1],256-strlen(namebuf)-strlen(&name[i-1]));
- debug(F110,"ckgetfqhn()",namebuf,0);
- return(namebuf);
- #endif /* NOCKGETFQHOST */
- }
- VOID
- #ifdef CK_ANSIC
- setnproto(char * p)
- #else
- setnproto(p) char * p;
- #endif /* CK_ANSIC */
- {
- if (!isdigit(*p)) {
- if (!strcmp("kermit",p))
- ttnproto = NP_KERMIT;
- else if (!strcmp("telnet",p))
- ttnproto = NP_TELNET;
- else if (!strcmp("http",p))
- ttnproto = NP_TCPRAW;
- #ifdef RLOGCODE
- else if (!strcmp("login",p))
- ttnproto = NP_RLOGIN;
- #endif /* RLOGCODE */
- #ifdef CK_SSL
- /* Commonly used SSL ports (might not be in services file) */
- else if (!strcmp("https",p)) {
- ttnproto = NP_SSL_RAW;
- ssl_only_flag = 1;
- } else if (!strcmp("ssl-telnet",p)) {
- ttnproto = NP_TELNET;
- ssl_only_flag = 1;
- } else if (!strcmp("telnets",p)) {
- ttnproto = NP_TELNET;
- ssl_only_flag = 1;
- }
- #endif /* CK_SSL */
- #ifdef CK_KERBEROS
- #ifdef RLOGCODE
- else if (!strcmp("klogin",p)) {
- if (ck_krb5_is_installed())
- ttnproto = NP_K5LOGIN;
- else if (ck_krb4_is_installed())
- ttnproto = NP_K4LOGIN;
- else
- ttnproto = NP_RLOGIN;
- } else if (!strcmp("eklogin",p)) {
- if (ck_krb5_is_installed())
- ttnproto = NP_EK5LOGIN;
- else if (ck_krb4_is_installed())
- ttnproto = NP_EK4LOGIN;
- else
- ttnproto = NP_RLOGIN;
- }
- #endif /* RLOGCODE */
- #endif /* CK_KERBEROS */
- else
- ttnproto = NP_NONE;
- } else {
- switch (atoi(p)) {
- case 23: /* Telnet */
- ttnproto = NP_TELNET;
- break;
- case 513:
- ttnproto = NP_RLOGIN;
- break;
- case 1649:
- ttnproto = NP_KERMIT;
- break;
- #ifdef CK_SSL
- case 443:
- #ifdef COMMENT
- /* Jeff 2005/12/30 */
- ttnproto = NP_SSL_RAW;
- #else
- /* fdc 2005/12/04 */
- ttnproto = NP_SSL;
- #endif /* COMMENT */
- ssl_only_flag = 1;
- break;
- case 151:
- case 992:
- ttnproto = NP_TELNET;
- ssl_only_flag = 1;
- break;
- #endif /* CK_SSL */
- #ifdef CK_KERBEROS
- case 543:
- if (ck_krb5_is_installed())
- ttnproto = NP_K5LOGIN;
- else if (ck_krb4_is_installed())
- ttnproto = NP_K4LOGIN;
- else
- ttnproto = NP_RLOGIN;
- break;
- case 2105:
- if (ck_krb5_is_installed())
- ttnproto = NP_EK5LOGIN;
- else if (ck_krb4_is_installed())
- ttnproto = NP_EK4LOGIN;
- else
- ttnproto = NP_RLOGIN;
- break;
- #endif /* CK_KERBEROS */
- case 80: /* HTTP */
- ttnproto = NP_TCPRAW;
- break;
- default:
- ttnproto = NP_NONE;
- break;
- }
- }
- }
- /* ckgetservice() is used to determine the port number for a given */
- /* service taking into account the use of DNS SRV records. */
- static struct servent servrec;
- static struct servent *
- ckgetservice(hostname, servicename, ip, iplen)
- char *hostname; char * servicename; char * ip; int iplen;
- {
- struct servent * service = NULL;
- #ifdef CK_DNS_SRV
- struct sockaddr * dns_addrs = NULL;
- int dns_naddrs = 0;
- #endif /* CK_DNS_SRV */
- if (isdigit(*servicename)) { /* Use socket number without lookup */
- service = &servrec;
- service->s_port = htons((unsigned short)atoi(servicename));
- } else { /* Otherwise lookup the service name */
- #ifdef CK_DNS_SRV
- if (tcp_dns_srv && !quiet) {
- printf(" DNS SRV Lookup... ");
- fflush(stdout);
- }
- if (tcp_dns_srv &&
- locate_srv_dns(hostname,
- servicename,
- "tcp",
- &dns_addrs,
- &dns_naddrs
- )
- ) {
- /* Use the first one. Eventually we should cycle through all */
- /* the returned IP addresses and port numbers. */
- struct sockaddr_in *sin = NULL;
- #ifdef BETADEBUG
- int i;
- printf("\r\n");
- for ( i=0;i<dns_naddrs;i++ ) {
- sin = (struct sockaddr_in *) &dns_addrs[i];
- printf("dns_addrs[%d] = %s %d\r\n", i,
- (char *)inet_ntoa(sin->sin_addr),
- ntohs(sin->sin_port));
- }
- #endif /* BETADEBUG */
- sin = (struct sockaddr_in *) &dns_addrs[0];
- if ( ip && iplen > 0 )
- ckstrncpy(ip,(char *)inet_ntoa(sin->sin_addr),iplen);
- service = &servrec;
- service->s_port = sin->sin_port;
- free(dns_addrs);
- dns_addrs = NULL;
- dns_naddrs = 0;
- } else
- #endif /* CK_DNS_SRV */
- service = getservbyname(servicename, "tcp");
- }
- if (!service) {
- if (!ckstrcmp("kermit",servicename,-1,0)) { /* Kermit service port */
- service = &servrec;
- service->s_port = htons(1649);
- } else if (!ckstrcmp("telnet",servicename,-1,0)) { /* Telnet port */
- service = &servrec;
- service->s_port = htons(23);
- } else if (!ckstrcmp("http",servicename,-1,0)) {
- service = &servrec;
- service->s_port = htons(80);
- }
- #ifdef RLOGCODE
- else if (!ckstrcmp("login",servicename,-1,0)) {
- service = &servrec;
- service->s_port = htons(513);
- }
- #endif /* RLOGCODE */
- #ifdef CK_SSL
- /* Commonly used SSL ports (might not be in services file) */
- else if (!ckstrcmp("https",servicename,-1,0)) {
- service = &servrec;
- service->s_port = htons(443);
- } else if (!ckstrcmp("ssl-telnet",servicename,-1,0)) {
- service = &servrec;
- service->s_port = htons(151);
- } else if (!ckstrcmp("telnets",servicename,-1,0)) {
- service = &servrec;
- service->s_port = htons(992);
- }
- #endif /* CK_SSL */
- #ifdef CK_KERBEROS
- #ifdef RLOGCODE
- else if (!ckstrcmp("klogin",servicename,-1,0)) {
- service = &servrec;
- service->s_port = htons(543);
- } else if (!ckstrcmp("eklogin",servicename,-1,0)) {
- service = &servrec;
- service->s_port = htons(2105);
- }
- #endif /* RLOGCODE */
- #endif /* CK_KERBEROS */
- }
- return(service);
- }
- /* N E T O P E N -- Open a network connection */
- /*
- Calling conventions same as ttopen(), except third argument is network
- type rather than modem type. Designed to be called from within ttopen.
- */
- #define XXNAMELEN 256
- static char xxname[XXNAMELEN];
- int
- netopen(name, lcl, nett) char *name; int *lcl, nett; {
- char *p;
- int i, x, rc_inet_addr = 0, dns = 0;
- #ifdef TCPSOCKET
- int isconnect = 0;
- #ifdef SO_OOBINLINE
- int on = 1;
- #endif /* SO_OOBINLINE */
- struct servent *service=NULL;
- struct hostent *host=NULL;
- struct sockaddr_in r_addr;
- struct sockaddr_in sin;
- struct sockaddr_in l_addr;
- GSOCKNAME_T l_slen;
- #ifdef EXCELAN
- struct sockaddr_in send_socket;
- #endif /* EXCELAN */
- #ifdef INADDRX
- /* inet_addr() is of type struct in_addr */
- #ifdef datageneral
- extern struct in_addr inet_addr();
- #else
- #ifdef HPUX5WINTCP
- extern struct in_addr inet_addr();
- #endif /* HPUX5WINTCP */
- #endif /* datageneral */
- struct in_addr iax;
- #else
- #ifdef INADDR_NONE
- struct in_addr iax;
- #else /* INADDR_NONE */
- long iax;
- #endif /* INADDR_NONE */
- #endif /* INADDRX */
- #endif /* TCPSOCKET */
- #ifdef COMMENT
- /* This causes big trouble */
- #ifndef INADDR_NONE
- #define INADDR_NONE 0xffffffff
- #endif /* INADDR_NONE */
- #endif /* COMMENT */
- #ifdef SUNX25 /* Code for SunLink X.25 support */
- #define X29PID 1 /* X.29 Protocol ID */
- _PROTOTYP(SIGTYP x25oobh, (int) );
- CONN_DB x25host;
- #ifndef X25_WR_FACILITY
- FACILITY x25facil;
- #else
- FACILITY_DB x25facil;
- #endif /* X25_WR_FACILITY */
- static int needh = 1;
- PID_T pid;
- extern int linkid, lcn, x25ver;
- #endif /* SUNX25 */
- #ifdef ANYX25
- extern int revcall, closgr, cudata;
- extern char udata[];
- #endif /* ANYX25 */
- #ifdef IBMX25 /* Variables for IBM X25 */
- extern int x25port; /* Logical port to use */
- extern x25addr_t local_nua; /* Local X.25 address */
- extern x25addr_t remote_nua; /* Remote X.25 address */
- extern char x25name[]; /* X25 device name (sx25a0) */
- extern char x25dev[]; /* X25 device file /dev/x25pkt */
- ulong bind_flags = 0; /* Flags for binding the X25 stream */
- ulong token = 0; /* Temporary return code */
- #endif /* IBMX25 */
- debug(F101,"netopen nett","",nett);
- *ipaddr = '\0'; /* Initialize IP address string */
- #ifdef SUNX25
- if (nett == NET_SX25) { /* If network type is X.25 */
- netclos(); /* Close any previous net connection */
- ttnproto = NP_NONE; /* No protocol selected yet */
- /* Set up host structure */
- bzero((char *)&x25host,sizeof(x25host));
- if ((x25host.hostlen = pkx121(name,x25host.host)) < 0) {
- fprintf (stderr,"Invalid X.121 host address %s\n",name);
- errno = 0;
- return (-1);
- }
- x25host.datalen = X29PIDLEN;
- x25host.data[0] = X29PID;
- /* Set call user data if specified */
- if (cudata) {
- ckstrncpy((char *)x25host.data+X29PIDLEN,udata,(int)strlen(udata));
- x25host.datalen += (int)strlen(udata);
- }
- /* Open SunLink X.25 socket */
- if (!quiet && *name) {
- printf(" Trying %s... ", name);
- fflush(stdout);
- }
- if ((ttyfd = socket(AF_X25, SOCK_STREAM, 0)) < 0) {
- debug(F101,"netopen socket error","",errno);
- perror ("X.25 socket error");
- return (-1);
- }
- /* Setting X.25 out-of-band data handler */
- pid = getpid();
- if (ioctl(ttyfd,SIOCSPGRP,&pid)) {
- perror("X.25 set process group id error");
- return(-1);
- }
- (VOID) signal(SIGURG,x25oobh);
- /* Set reverse charge call and closed user group if requested */
- bzero ((char *)&x25facil,sizeof(x25facil));
- #ifndef X25_WR_FACILITY
- /* New SunLink (7.0 or 8.0, not sure which)... */
- x25facil.type = T_REVERSE_CHARGE; /* Reverse Charge */
- x25facil.f_reverse_charge = revcall ? 1 : 0;
- if (ioctl(ttyfd,X25_SET_FACILITY,&x25facil) < 0) {
- perror ("Setting X.25 reverse charge");
- return (-1);
- }
- if (closgr > -1) { /* Closed User Group (Outgoing) */
- bzero ((char *)&x25facil,sizeof(x25facil));
- x25facil.type = T_CUG;
- x25facil.f_cug_req = CUG_REQ_ACS;
- x25facil.f_cug_index = closgr;
- if (ioctl(ttyfd,X25_SET_FACILITY,&x25facil) < 0) {
- perror ("Setting X.25 closed user group");
- return (-1);
- }
- }
- #else
- /* Old SunLink 6.0 (or 7.0?)... */
- if (revcall) x25facil.reverse_charge = revcall;
- if (closgr > -1) {
- x25facil.cug_req = 1;
- x25facil.cug_index = closgr;
- }
- if (ioctl(ttyfd,X25_WR_FACILITY,&x25facil) < 0) {
- perror ("Setting X.25 facilities");
- return (-1);
- }
- #endif /* X25_WR_FACILITY */
- /* Need X.25 header with bits Q and M */
- if (ioctl (ttyfd,X25_HEADER,&needh) < 0) {
- perror ("Setting X.25 header");
- return (-1);
- }
- /* Connects to remote host via SunLink X.25 */
- if (connect(ttyfd,(struct sockaddr *)&x25host,sizeof(x25host)) < 0) {
- i = errno;
- debug(F101,"netopen connect errno","",i);
- if (i) {
- perror("netopen x25 connect");
- x25diag();
- }
- (VOID) netclos();
- ttyfd = -1;
- wasclosed = 1;
- ttnproto = NP_NONE;
- errno = i;
- return (-1);
- }
- /* Get X.25 link identification used for the connection */
- if (ioctl(ttyfd,X25_GET_LINK,&linkid) < 0) {
- perror ("Getting X.25 link id");
- return (-1);
- }
- /* Get X.25 logical channel number used for the connection */
- if (ioctl(ttyfd,X25_RD_LCGN,&lcn) < 0) {
- perror ("Getting X.25 lcn");
- return (-1);
- }
- /* Get SunLink X.25 version */
- if (ioctl(ttyfd,X25_VERSION,&x25ver) < 0) {
- perror ("Getting SunLink X.25 version");
- return (-1);
- }
- ttnet = nett; /* Sunlink X.25 network */
- ttnproto = NP_X3; /* PAD X.3, X.28, X.29 protocol */
- if (lcl) if (*lcl < 0) *lcl = 1; /* Local mode */
- return(0);
- } else /* Note that SUNX25 support can coexist with TCP/IP support. */
- #endif /* SUNX25 */
- #ifdef IBMX25
- /* riehm */
- if (nett == NET_IX25) { /* IBM AIX X.25 */
- netclos(); /* Close any previous net connection */
- ttnproto = NP_NONE; /* No protocol selected yet */
- /* find out who we are - this is not so easy on AIX */
- /* riehm: need to write the code that finds this out
- * automatically, or at least allow it to be configured
- * somehow
- */
- if (!local_nua[0] && !x25local_nua(local_nua)) {
- return(-1);
- }
- /* Initialise the X25 API (once per process? once per connection?) */
- debug(F110, "Opening ", x25dev, 0 );
- /* set O_NDELAY to allow polling? */
- if ((ttyfd = open(x25dev, O_RDWR)) < 0) {
- perror ("X.25 device open error");
- debug(F101,"netopen: device open error","",errno);
- return (-1);
- }
- /* push the NPI onto the STREAM */
- if (ioctl(ttyfd,I_PUSH,"npi") < 0 ) {
- close(ttyfd);
- ttyfd = -1;
- wasclosed = 1;
- perror( "kermit: netopen(): couldn't push npi on the X25 stream" );
- debug(F101,"netopen: can't push npi on the X25 stream","",errno);
- return (-1);
- }
- /* set up server mode - bind the x25 port and wait for
- * incoming connections
- */
- if (name[0] == '*') { /* Server */
- /* set up a server - see the warning in x25bind() */
- bind_flags |= TOKEN_REQUEST;
- /* bind kermit to the local X25 address */
- token = x25bind(ttyfd,
- local_nua,
- udata,
- (int)strlen( udata ),
- 1,
- x25port,
- bind_flags
- );
- if (token < 0) {
- debug(F100,"netopen: couldn't bind to local X25 address","",0);
- netclos();
- return(-1);
- }
- /* Currently not connected to a remote host */
- remote_nua[0] = '\0';
- /* store the fd so that incoming calls can have their own fd
- * This is almost support for a true server (ie: a'la ftpd)
- * but we're not quite there yet.
- * used in netclos()
- */
- x25serverfd = ttyfd;
- /*
- * wait for an incoming call
- * this should happen in the "server" command and not in
- * the "set host *" command.
- */
- if ((ttyfd = x25getcall(ttyfd)) < 0) {
- netclos();
- return(-1);
- }
- } else { /* Client */
- /* Bind kermit to the local X25 address */
- token = x25bind(
- ttyfd,
- local_nua,
- (char *)NULL,
- 0,
- 0,
- x25port,
- bind_flags
- );
- if (token < 0) {
- debug(F100,"netopen: couldn't bind to local X25 address","",0);
- netclos();
- return(-1);
- }
- /* riehm: this should be done via the CONNECT command, not HOST! */
- {
- x25serverfd = 0;
- /* call the remote host */
- /* name == address of remote host as char* */
- if (x25call(ttyfd, name, udata) < 0 ) {
- debug(F100,
- "netopen: couldn't connect to remote X25 address",
- "", 0);
- netclos();
- return(-1);
- }
- strcpy(remote_nua, name);
- }
- }
- ttnet = nett; /* AIX X.25 network */
- if (lcl) if (*lcl < 0) *lcl = 1; /* Local mode */
- return(0);
- } else /* Note that IBMX25 support can coexist with TCP/IP support. */
- #endif /* IBMX25 */
- /* Add support for other networks here. */
- if (nett != NET_TCPB) return(-1); /* BSD socket support */
- #ifdef TCPSOCKET
- netclos(); /* Close any previous connection. */
- ckstrncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
- debug(F110,"netopen namecopy",namecopy,0);
- #ifndef NOLISTEN
- if (name[0] == '*')
- return(tcpsrv_open(name, lcl, nett, 0));
- #endif /* NOLISTEN */
- p = namecopy; /* Was a service requested? */
- while (*p != '\0' && *p != ':') p++; /* Look for colon */
- if (*p == ':') { /* Have a colon */
- debug(F110,"netopen name has colon",namecopy,0);
- *p++ = '\0'; /* Get service name or number */
- #ifdef CK_URL
- /*
- Here we have to check for various popular syntaxes:
- host:port (our original syntax)
- URL such as telnet:host or telnet://host/
- Or even telnet://user:password@host:port/path/
- Or a malformed URL such as generated by Netscape 4.0 like:
- telnet:telnet or telnet::host.
- */
- /*
- * REPLACE THIS CODE WITH urlparse() but not on the day of the
- * C-Kermit 8.0 RELEASE.
- */
- if (*p == ':') /* a second colon */
- *p++ = '\0'; /* get rid of that one too */
- while (*p == '/') *p++ = '\0'; /* and slashes */
- x = strlen(p); /* Length of remainder */
- if (p[x-1] == '/') /* If there is a trailing slash */
- p[x-1] = '\0'; /* remove it. */
- debug(F110,"netopen namecopy after stripping",namecopy,0);
- debug(F110,"netopen p after stripping",p,0);
- service = getservbyname(namecopy,"tcp");
- if (service ||
- #ifdef RLOGCODE
- !ckstrcmp("rlogin",namecopy,NAMECPYL,0) ||
- #endif /* RLOGCODE */
- #ifdef CK_SSL
- !ckstrcmp("telnets",namecopy,NAMECPYL,0) ||
- #endif /* CK_SSL */
- !ckstrcmp("iksd",namecopy,NAMECPYL,0)
- ) {
- char temphost[256], tempservice[80], temppath[256];
- char * q = p, *r = p, *w = p;
- int uidfound=0;
- extern char pwbuf[];
- extern int pwflg, pwcrypt;
- if (ttnproto == NP_DEFAULT)
- setnproto(namecopy);
- /* Check for userid and possibly password */
- while (*p != '\0' && *p != '@')
- p++; /* look for @ */
- if (*p == '@') {
- /* found username and perhaps password */
- debug(F110,"netopen namecopy found @","",0);
- *p = '\0';
- p++;
- while (*w != '\0' && *w != ':')
- w++;
- if (*w == ':')
- *w++ = '\0';
- /* r now points to username, save it and the password */
- debug(F110,"netopen namecopy username",r,0);
- debug(F110,"netopen namecopy password",w,0);
- uidfound=1;
- if ( strcmp(uidbuf,r) || *w )
- ckstrncpy(pwbuf,w,PWBUFL+1);
- ckstrncpy(uidbuf,r,UIDBUFLEN);
- pwflg = 1;
- pwcrypt = 0;
- q = p; /* Host after user and pwd */
- } else {
- p = q; /* No username or password */
- }
- /* Now we must look for the optional port. */
- debug(F110,"netopen x p",p,0);
- debug(F110,"netopen x q",q,0);
- /* Look for the port/service or a file/directory path */
- while (*p != '\0' && *p != ':' && *p != '/')
- p++;
- if (*p == ':') {
- debug(F110,"netopen found port",q,0);
- *p++ = '\0'; /* Found a port name or number */
- r = p;
- /* Look for the end of port/service or a file/directory path */
- while (*p != '\0' && *p != '/')
- p++;
- if (*p == '/')
- *p++ = '\0';
- debug(F110,"netopen port",r,0);
- ckstrncpy(tempservice,r,80);
- ckstrncpy(temphost,q,256);
- ckstrncpy(temppath,p,256);
- ckstrncpy(namecopy,temphost,NAMECPYL);
- debug(F110,"netopen tempservice",tempservice,0);
- debug(F110,"netopen temphost",temphost,0);
- debug(F110,"netopen temppath",temppath,0);
- /* move port/service to a buffer that won't go away */
- x = strlen(namecopy);
- p = namecopy + x + 1;
- ckstrncpy(p, tempservice, NAMECPYL - x);
- } else {
- /* Handle a path if we found one */
- if (*p == '/')
- *p++ = '\0';
- ckstrncpy(temppath,p,256);
- /* We didn't find another port, but if q is a service */
- /* then assume that namecopy is actually a host. */
- if (getservbyname(q,"tcp")) {
- p = q;
- } else {
- #ifdef RLOGCODE
- /* rlogin is not a valid service */
- if (!ckstrcmp("rlogin",namecopy,6,0)) {
- ckstrncpy(namecopy,"login",NAMECPYL);
- }
- #endif /* RLOGCODE */
- /* iksd is not a valid service */
- if (!ckstrcmp("iksd",namecopy,6,0)) {
- ckstrncpy(namecopy,"kermit",NAMECPYL);
- }
- /* Reconstruct namecopy */
- ckstrncpy(tempservice,namecopy,80);
- ckstrncpy(temphost,q,256);
- ckstrncpy(namecopy,temphost,NAMECPYL);
- debug(F110,"netopen tempservice",tempservice,0);
- debug(F110,"netopen temphost",temphost,0);
- debug(F110,"netopen temppath",temppath,0);
- /* move port/service to a buffer that won't go away */
- x = strlen(namecopy);
- p = namecopy + x + 1;
- ckstrncpy(p, tempservice, NAMECPYL - x - 1);
- }
- }
- debug(F110,"netopen URL result: host",namecopy,0);
- debug(F110,"netopen URL result: service",p,0);
- debug(F110,"netopen URL result: path",temppath,0);
- #ifdef IKS_GET
- /* If we have set a path specified, we need to try to GET it */
- /* But we have another problem, we have to login first. How */
- /* do we specify that a login must be done before the GET? */
- /* The user's name if specified is in 'userid' and the */
- /* password if any is in 'pwbuf'. */
- if ( temppath[0] ) {
- extern int action;
- extern char * cmarg;
- if ( !uidfound ) {
- /* If no userid was specified as part of the URL but
- * a path was specified, then we
- * set the user name to anonymous and the password
- * to the current userid.
- */
- ckstrncpy(pwbuf,uidbuf,PWBUFL);
- ckstrncat(pwbuf,"@",PWBUFL);
- pwflg = 1;
- pwcrypt = 0;
- ckstrncpy(uidbuf,"anonymous",UIDBUFLEN);
- }
- /*
- * If a file path was specified we perform the GET
- * operation and then terminate the connection.
- *
- * If a directory was given instead of a file, then
- * we should REMOTE CD to the directory and list its
- * contents. But how do we tell the difference?
- */
- makestr(&cmarg,temppath);
- action = 'r';
- }
- #endif /* IKS_GET */
- }
- #endif /* CK_URL */
- } else { /* Otherwise use telnet */
- p = "telnet";
- }
- /*
- By the time we get here, namecopy[] should hold the null-terminated
- hostname or address, and p should point to the service name or number.
- */
- debug(F110,"netopen host",namecopy,0);
- debug(F110,"netopen service requested",p,0);
- /* Use the service port to set the default protocol type if necessary */
- if (ttnproto == NP_DEFAULT)
- setnproto(p);
- ckstrncpy(namecopy2,namecopy,NAMECPYL);
- service = ckgetservice(namecopy,p,namecopy,NAMECPYL);
- if (!service) {
- fprintf(stderr, "Can't find port for service %s\n", p);
- #ifdef TGVORWIN
- debug(F101,"netopen can't get service","",socket_errno);
- #else
- debug(F101,"netopen can't get service","",errno);
- #endif /* TGVORWIN */
- errno = 0; /* (rather than mislead) */
- return(-1);
- } else {
- if (!ckstrcmp(namecopy,namecopy2,-1,0))
- namecopy2[0] = '\0';
- ckstrncpy(svcbuf,ckuitoa(ntohs(service->s_port)),sizeof(svcbuf));
- debug(F110,"netopen service ok",svcbuf,0);
- }
- #ifdef RLOGCODE
- if (service && !strcmp("login",p) && service->s_port != htons(513)) {
- fprintf(stderr,
- " Warning: login service on port %d instead of port 513\n",
- ntohs(service->s_port)
- );
- fprintf(stderr, " Edit SERVICES file if RLOGIN fails to connect.\n");
- debug(F101,"tcpsrv_open login on port","",ntohs(service->s_port));
- }
- #endif /* RLOGCODE */
- #ifndef NOHTTP
- /* For HTTP connections we must preserve the original hostname and */
- /* service requested so we can include them in the Host header. */
- ckmakmsg(http_host_port,sizeof(http_host_port),namecopy,":",
- ckitoa(ntohs(service->s_port)),NULL);
- /* 'namecopy' contains the name of the host to which we want to connect */
- /* 'svcbuf' contains the service name */
- /* 'service->s_port' contains the port number in network byte order */
- /* If we are using an http proxy, we need to create a buffer containing */
- /* hostname:port-number */
- /* to pass to the http_connect() function. Then we need to replace */
- /* 'namecopy' with the name of the proxy server and the service->s_port */
- /* with the port number of the proxy (default port 80). */
- if ( tcp_http_proxy ) {
- ckmakmsg(proxycopy,sizeof(proxycopy),namecopy,":",
- ckuitoa(ntohs(service->s_port)),NULL);
- ckstrncpy(namecopy,tcp_http_proxy,NAMECPYL);
- p = namecopy; /* Was a service requested? */
- while (*p != '\0' && *p != ':') p++; /* Look for colon */
- if (*p == ':') { /* Have a colon */
- debug(F110,"netopen name has colon",namecopy,0);
- *p++ = '\0'; /* Get service name or number */
- } else {
- strcpy(++p,"http");
- }
- service = ckgetservice(namecopy,p,namecopy,NAMECPYL);
- if (!service) {
- fprintf(stderr, "Can't find port for service %s\n", p);
- #ifdef TGVORWIN
- debug(F101,"netopen can't get service for proxy","",socket_errno);
- #else
- debug(F101,"netopen can't get service for proxy","",errno);
- #endif /* TGVORWIN */
- errno = 0; /* (rather than mislead) */
- return(-1);
- }
- ckstrncpy(p,ckuitoa(ntohs(service->s_port)),NAMECPYL-(p-namecopy));
- }
- #endif /* NOHTTP */
- /* Set up socket structure and get host address */
- bzero((char *)&r_addr, sizeof(r_addr));
- debug(F100,"netopen bzero ok","",0);
- /*
- NOTE: Originally the inet_addr() check was #ifdef NT, but is enabled for
- all as of 20 Sep 97, to allow people to "set host" to a specific numeric IP
- address without going through the multihomed host sequence and winding up
- at a different place than the one requested.
- */
- #ifdef INADDR_NONE
- debug(F101,"netopen INADDR_NONE defined","",INADDR_NONE);
- #else /* INADDR_NONE */
- debug(F100,"netopen INADDR_NONE not defined","",0);
- #endif /* INADDR_NONE */
- #ifdef INADDRX
- debug(F100,"netopen INADDRX defined","",0);
- #else /* INADDRX */
- debug(F100,"netopen INADDRX not defined","",0);
- #endif /* INADDRX */
- #ifndef NOMHHOST
- #ifdef INADDRX
- iax = inet_addr(namecopy);
- debug(F111,"netopen inet_addr",namecopy,iax.s_addr);
- #else /* INADDRX */
- #ifdef INADDR_NONE
- iax.s_addr = inet_addr(namecopy);
- debug(F111,"netopen inet_addr",namecopy,iax.s_addr);
- #else /* INADDR_NONE */
- #ifdef SOLARIS
- /* In Solaris inet_addr() is of type in_addr_t which is uint32_t */
- /* (unsigned) yet it returns -1 (signed) on failure. */
- /* It makes a difference in 64-bit builds. */
- rc_inet_addr = inet_addr(namecopy); /* Assign return code to an int */
- iax = (unsigned) rc_inet_addr; /* and from there to whatever.. */
- #else
- #ifndef datageneral
- iax = (unsigned int) inet_addr(namecopy);
- #else
- iax = -1L;
- #endif /* datageneral */
- #endif /* SOLARIS */
- debug(F111,"netopen rc_inet_addr",namecopy,rc_inet_addr);
- debug(F111,"netopen inet_addr",namecopy,iax);
- #endif /* INADDR_NONE */
- #endif /* INADDRX */
- dns = 0;
- if (
- /* This might give warnings on 64-bit platforms but they should be harmless */
- /* because INADDR_NONE should be all 1's anyway, thus the OR part is */
- /* probably superfluous -- not sure why it's even there, maybe it should be */
- /* removed. */
- #ifdef SOLARIS
- rc_inet_addr == -1
- #else
- #ifdef INADDR_NONE
- iax.s_addr == INADDR_NONE /* || iax.s_addr == (unsigned long) -1L */
- #else /* INADDR_NONE */
- iax < 0
- #endif /* INADDR_NONE */
- #endif /* SOLARIS */
- ) {
- if (!quiet) {
- printf(" DNS Lookup... ");
- fflush(stdout);
- }
- if ((host = gethostbyname(namecopy)) != NULL) {
- debug(F110,"netopen gethostbyname != NULL",namecopy,0);
- host = ck_copyhostent(host);
- dns = 1; /* Remember we performed dns lookup */
- r_addr.sin_family = host->h_addrtype;
- if (tcp_rdns && host->h_name && host->h_name[0]
- #ifndef NOHTTP
- && (tcp_http_proxy == NULL)
- #endif /* NOHTTP */
- ) {
- #ifdef COMMENT
- ckstrncpy(xxname,host->h_name,XXNAMELEN);
- debug(F110,"netopen xxname[1]",xxname,0);
- if ((XXNAMELEN - (int)strlen(name)) > ((int)strlen(svcbuf)+1)){
- ckstrncat(xxname,":",XXNAMELEN - (int)strlen(xxname));
- ckstrncat(xxname,svcbuf,XXNAMELEN - (int)strlen(xxname));
- debug(F110,"netopen xxname[2]",xxname,0);
- }
- name = (char *)xxname;
- #else
- ckstrncpy(name,host->h_name,80); /* Bad Bad Bad */
- if ( (80-strlen(name)) > (strlen(svcbuf)+1) ) {
- ckstrncat(name,":",80-strlen(name));
- ckstrncat(name,svcbuf,80-strlen(name));
- }
- #endif /* COMMENT */
- }
- debug(F110,"netopen name after lookup",name,0);
- #ifdef HADDRLIST
- #ifdef h_addr
- /* This is for trying multiple IP addresses - see <netdb.h> */
- if (!(host->h_addr_list))
- return(-1);
- bcopy(host->h_addr_list[0],
- (caddr_t)&r_addr.sin_addr,
- host->h_length
- );
- #else
- bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
- #endif /* h_addr */
- #else /* HADDRLIST */
- #ifdef HPUX6
- r_addr.sin_addr.s_addr = (u_long)host->h_addr;
- #else /* HPUX6 */
- bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
- #endif /* HPUX6 */
- #endif /* HADDRLIST */
- #ifndef HPUX6
- debug(F111,"BCOPY","host->h_length",host->h_length);
- #endif /* HPUX6 */
- }
- }
- #endif /* NOMHHOST */
- debug(F101,"netopen dns","",dns);
- if (!dns) {
- #ifdef INADDRX
- /* inet_addr() is of type struct in_addr */
- struct in_addr ina;
- unsigned long uu;
- debug(F100,"netopen gethostbyname == NULL: INADDRX","",0);
- ina = inet_addr(namecopy);
- uu = *(unsigned int *)&ina;
- #else /* Not INADDRX */
- /* inet_addr() is unsigned long */
- unsigned long uu;
- debug(F100,"netopen gethostbyname == NULL: Not INADDRX","",0);
- uu = inet_addr(namecopy);
- #endif /* INADDRX */
- debug(F101,"netopen uu","",uu);
- if (
- #ifdef INADDR_NONE
- !(uu == INADDR_NONE || uu == (unsigned int) -1L)
- #else /* INADDR_NONE */
- uu != ((unsigned long)-1)
- #endif /* INADDR_NONE */
- ) {
- r_addr.sin_addr.s_addr = uu;
- r_addr.sin_family = AF_INET;
- } else {
- #ifdef VMS
- fprintf(stdout, "\r\n"); /* complete any previous message */
- #endif /* VMS */
- fprintf(stderr, "Can't get address for %s\n", namecopy);
- #ifdef TGVORWIN
- debug(F101,"netopen can't get address","",socket_errno);
- #else
- debug(F101,"netopen can't get address","",errno);
- #endif /* TGVORWIN */
- errno = 0; /* Rather than mislead */
- return(-1);
- }
- }
- /* Get a file descriptor for the connection. */
- r_addr.sin_port = service->s_port;
- ckstrncpy(ipaddr,(char *)inet_ntoa(r_addr.sin_addr),20);
- debug(F110,"netopen trying",ipaddr,0);
- if (!quiet && *ipaddr) {
- printf(" Trying %s... ", ipaddr);
- fflush(stdout);
- }
- /* Loop to try additional IP addresses, if any. */
- do {
- #ifdef EXCELAN
- send_socket.sin_family = AF_INET;
- send_socket.sin_addr.s_addr = 0;
- send_socket.sin_port = 0;
- if ((ttyfd = socket(SOCK_STREAM, (struct sockproto *)0,
- &send_socket, SO_REUSEADDR)) < 0)
- #else /* EXCELAN */
- #ifdef NT
- #ifdef COMMENT_X
- /*
- Must make sure that all sockets are opened in
- Non-overlapped mode since we use the standard
- C RTL functions to read and write data.
- But it doesn't seem to work as planned.
- */
- {
- int optionValue = SO_SYNCHRONOUS_NONALERT;
- if (setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *) &optionValue, sizeof(optionValue))
- != NO_ERROR)
- return(-1);
- }
- #endif /* COMMENT */
- #endif /* NT */
- if ((ttyfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- #endif /* EXCELAN */
- {
- #ifdef EXCELAN
- experror("TCP socket error");
- #else
- #ifdef VMS
- fprintf(stdout, "\r\n"); /* complete any previous stdout */
- #endif /* VMS */
- #ifdef TGVORWIN
- #ifdef OLD_TWG
- errno = socket_errno;
- #endif /* OLD_TWG */
- socket_perror("TCP socket error");
- debug(F101,"netopen socket error","",socket_errno);
- #else
- perror("TCP socket error");
- debug(F101,"netopen socket error","",errno);
- #endif /* TGVORWIN */
- #endif /* EXCELAN */
- return (-1);
- }
- errno = 0;
- #ifdef RLOGCODE
- /* Not part of the RLOGIN RFC, but the BSD implementation */
- /* requires that the client port be a priviliged port (<1024) */
- /* on a Unix system this would require SuperUser permissions */
- /* thereby saying that the root of the Unix system has given */
- /* permission for this connection to be created */
- if (service->s_port == htons((unsigned short)RLOGIN_PORT)) {
- static unsigned short lport = 1024; /* max reserved port */
- #ifdef OS2
- int s_errno;
- #endif /* OS2 */
- lport--; /* Make sure we do not reuse a port */
- if (lport == 512)
- lport = 1023;
- sin.sin_family = AF_INET;
- if (tcp_address) {
- #ifdef INADDRX
- inaddrx = inet_addr(tcp_address);
- sin.sin_addr.s_addr = *(unsigned long *)&inaddrx;
- #else
- sin.sin_addr.s_addr = inet_addr(tcp_address);
- #endif /* INADDRX */
- } else
- sin.sin_addr.s_addr = INADDR_ANY;
- while (1) {
- sin.sin_port = htons(lport);
- if (bind(ttyfd, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
- break;
- #ifdef OS2
- s_errno = socket_errno;
- if (s_errno && /* OS2 bind fails with 0, if already in use */
- #ifdef NT
- s_errno != WSAEADDRINUSE
- #else
- s_errno != SOCEADDRINUSE &&
- s_errno != (SOCEADDRINUSE - SOCBASEERR)
- #endif /* NT */
- )
- #else /* OS2 */
- #ifdef TGVORWIN
- if (socket_errno != EADDRINUSE)
- #else
- if (errno != EADDRINUSE)
- #endif /* TGVORWIN */
- #endif /* OS2 */
- {
- #ifdef COMMENT
- printf("\nBind failed with errno %d for port %d.\n",
- #ifdef OS2
- s_errno
- #else
- #ifdef TGVORWIN
- socket_errno
- #else
- errno
- #endif /* TGVORWIN */
- #endif /* OS2 */
- , lport
- );
- #ifdef OS2
- debug(F101,"rlogin bind failed","",s_errno);
- #else
- #ifdef TGVORWIN
- debug(F101,"rlogin bind failed","",socket_errno);
- #ifdef OLD_TWG
- errno = socket_errno;
- #endif /* OLD_TWG */
- socket_perror("rlogin bind");
- #else
- debug(F101,"rlogin bind failed","",errno);
- perror("rlogin bind");
- #endif /* TGVORWIN */
- #endif /* OS2 */
- #else /* COMMENT */
- #ifdef OS2
- debug(F101,"rlogin bind s_errno","",s_errno);
- perror("rlogin bind");
- #else
- #ifdef VMS
- printf("\r\n"); /* complete any previous message */
- #endif /* VMS */
- #ifdef TGVORWIN
- debug(F101,"rlogin bind socket_errno","",socket_errno);
- #ifdef OLD_TWG
- errno = socket_errno;
- #endif /* OLD_TWG */
- socket_perror("rlogin bind");
- #else
- debug(F101,"rlogin bind errno","",errno);
- perror("rlogin bind");
- #endif /* TGVORWIN */
- #endif /* OS2 */
- debug(F101,"rlogin local port","",lport);
- #endif /* COMMENT */
- netclos();
- return -1;
- }
- lport--;
- if (lport == 512 /* lowest reserved port to use */ ) {
- printf("\nNo reserved ports available.\n");
- netclos();
- return -1;
- }
- }
- debug(F101,"rlogin lport","",lport);
- ttnproto = NP_RLOGIN;
- } else
- #endif /* RLOGCODE */
- /* If a specific TCP address on the local host is desired we */
- /* must bind it to the socket. */
- #ifndef datageneral
- if (tcp_address) {
- int s_errno;
- debug(F110,"netopen binding socket to",tcp_address,0);
- bzero((char *)&sin,sizeof(sin));
- sin.sin_family = AF_INET;
- #ifdef INADDRX
- inaddrx = inet_addr(tcp_address);
- sin.sin_addr.s_addr = *(unsigned long *)&inaddrx;
- #else
- sin.sin_addr.s_addr = inet_addr(tcp_address);
- #endif /* INADDRX */
- sin.sin_port = 0;
- if (bind(ttyfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- s_errno = socket_errno; /* Save error code */
- #ifdef TCPIPLIB
- socket_close(ttyfd);
- #else /* TCPIPLIB */
- close(ttyfd);
- #endif /* TCPIPLIB */
- ttyfd = -1;
- wasclosed = 1;
- errno = s_errno; /* and report this error */
- debug(F101,"netopen bind errno","",errno);
- return(-1);
- }
- }
- #endif /* datageneral */
- /* Now connect to the socket on the other end. */
- #ifdef EXCELAN
- if (connect(ttyfd, &r_addr) < 0)
- #else
- #ifdef NT
- WSASafeToCancel = 1;
- #endif /* NT */
- if (connect(ttyfd, (struct sockaddr *)&r_addr, sizeof(r_addr)) < 0)
- #endif /* EXCELAN */
- {
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- #ifdef OS2
- i = socket_errno;
- #else /* OS2 */
- #ifdef TGVORWIN
- i = socket_errno;
- #else
- i = errno; /* Save error code */
- #endif /* TGVORWIN */
- #endif /* OS2 */
- #ifdef RLOGCODE
- if (
- #ifdef OS2
- i && /* OS2 bind fails with 0, if already in use */
- #ifdef NT
- i == WSAEADDRINUSE
- #else
- (i == SOCEADDRINUSE ||
- i == (SOCEADDRINUSE - SOCBASEERR))
- #endif /* NT */
- #else /* OS2 */
- #ifdef TGVORWIN
- socket_errno == EADDRINUSE
- #else
- errno == EADDRINUSE
- #endif /* TGVORWIN */
- #endif /* OS2 */
- && ttnproto == NP_RLOGIN) {
- #ifdef TCPIPLIB
- socket_close(ttyfd); /* Close it. */
- #else
- close(ttyfd);
- #endif /* TCPIPLIB */
- continue; /* Try a different lport */
- }
- #endif /* RLOGCODE */
- #ifdef HADDRLIST
- #ifdef h_addr
- if (host && host->h_addr_list && host->h_addr_list[1]) {
- perror("");
- host->h_addr_list++;
- bcopy(host->h_addr_list[0],
- (caddr_t)&r_addr.sin_addr,
- host->h_length);
- ckstrncpy(ipaddr,(char *)inet_ntoa(r_addr.sin_addr),20);
- debug(F110,"netopen h_addr_list",ipaddr,0);
- if (!quiet && *ipaddr) {
- printf(" Trying %s... ", ipaddr);
- fflush(stdout);
- }
- #ifdef TCPIPLIB
- socket_close(ttyfd); /* Close it. */
- #else
- close(ttyfd);
- #endif /* TCPIPLIB */
- continue;
- }
- #endif /* h_addr */
- #endif /* HADDRLIST */
- netclos();
- ttyfd = -1;
- wasclosed = 1;
- ttnproto = NP_NONE;
- errno = i; /* And report this error */
- #ifdef EXCELAN
- if (errno) experror("netopen connect");
- #else
- #ifdef TGVORWIN
- debug(F101,"netopen connect error","",socket_errno);
- /* if (errno) socket_perror("netopen connect"); */
- #ifdef OLD_TWG
- errno = socket_errno;
- #endif /* OLD_TWG */
- if (!quiet)
- socket_perror("netopen connect");
- #else /* TGVORWIN */
- debug(F101,"netopen connect errno","",errno);
- #ifdef VMS
- if (!quiet)
- perror("\r\nFailed");
- #else
- if (!quiet)
- perror("Failed");
- #endif /* VMS */
- #ifdef DEC_TCPIP
- if (!quiet)
- perror("netopen connect");
- #endif /* DEC_TCPIP */
- #ifdef CMU_TCPIP
- if (!quiet)
- perror("netopen connect");
- #endif /* CMU_TCPIP */
- #endif /* TGVORWIN */
- #endif /* EXCELAN */
- return(-1);
- }
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- isconnect = 1;
- } while (!isconnect);
- #ifdef NON_BLOCK_IO
- on = 1;
- x = socket_ioctl(ttyfd,FIONBIO,&on);
- debug(F101,"netopen FIONBIO","",x);
- #endif /* NON_BLOCK_IO */
- #ifdef NT_TCP_OVERLAPPED
- OverlappedWriteInit();
- OverlappedReadInit();
- #endif /* NT_TCP_OVERLAPPED */
- ttnet = nett; /* TCP/IP (sockets) network */
- #ifndef NOHTTP
- /* We have succeeded in connecting to the HTTP PROXY. So now we */
- /* need to attempt to connect through the proxy to the actual host */
- /* If that is successful, we have to pretend that we made a direct */
- /* connection to the actual host. */
- if ( tcp_http_proxy ) {
- #ifdef OS2
- char * agent = "Kermit 95"; /* Default user agent */
- #else
- char * agent = "C-Kermit";
- #endif /* OS2 */
- if (http_connect(ttyfd,
- tcp_http_proxy_agent ? tcp_http_proxy_agent : agent,
- NULL,
- tcp_http_proxy_user,
- tcp_http_proxy_pwd,
- 0,
- proxycopy
- ) < 0) {
- netclos();
- return(-1);
- }
- ckstrncpy(namecopy,proxycopy,NAMECPYL);
- p = namecopy; /* Was a service requested? */
- while (*p != '\0' && *p != ':') p++; /* Look for colon */
- *p = '\0';
- }
- #endif /* NOHTTP */
- /* Jeff - Does this next block of code that set's the protocol */
- /* need to be here anymore? 5/10/2000 */
- /* There are certain magic port numbers that when used require */
- /* the use of specific protocols. Check this now before we */
- /* set the SO_OOBINLINE state or we might get it wrong. */
- x = ntohs((unsigned short)service->s_port);
- svcnum = x;
- /* See if the service is TELNET. */
- if (x == TELNET_PORT) {
- /* Yes, so if raw port not requested */
- #ifdef COMMENT
- /* Jeff 2005/12/30 */
- if (ttnproto != NP_TCPRAW && ttnproto != NP_SSL_RAW &&
- ttnproto != NP_TLS_RAW && ttnproto != NP_NONE)
- #else
- /* fdc 2005/12/04 */
- if (ttnproto != NP_TCPRAW && ttnproto != NP_NONE)
- #endif /* COMMENT */
- ttnproto = NP_TELNET; /* Select TELNET protocol. */
- }
- #ifdef RLOGCODE
- else if (x == RLOGIN_PORT) {
- ttnproto = NP_RLOGIN;
- }
- #ifdef CK_KERBEROS
- /* There is no good way to do this. If the user didn't tell */
- /* which one to use up front. We may guess wrong if the user */
- /* has both Kerberos versions installed and valid TGTs for each */
- else if (x == KLOGIN_PORT &&
- ttnproto != NP_K4LOGIN &&
- ttnproto != NP_K5LOGIN) {
- if (ck_krb5_is_installed() &&
- ck_krb5_is_tgt_valid())
- ttnproto = NP_K5LOGIN;
- else if (ck_krb4_is_installed() && ck_krb4_is_tgt_valid())
- ttnproto = NP_K4LOGIN;
- else
- ttnproto = NP_K4LOGIN;
- } else if (x == EKLOGIN_PORT &&
- ttnproto != NP_EK4LOGIN &&
- ttnproto != NP_EK5LOGIN) {
- if (ck_krb5_is_installed() && ck_krb5_is_tgt_valid())
- ttnproto = NP_EK5LOGIN;
- else if (ck_krb4_is_installed() && ck_krb4_is_tgt_valid())
- ttnproto = NP_EK4LOGIN;
- else
- ttnproto = NP_EK4LOGIN;
- }
- #endif /* CK_KERBEROS */
- #endif /* RLOGCODE */
- #ifdef IKS_OPTION
- else if (x == KERMIT_PORT) { /* IKS uses Telnet protocol */
- if (ttnproto == NP_NONE)
- ttnproto = NP_KERMIT;
- }
- #endif /* IKS_OPTION */
- #ifdef SO_OOBINLINE
- /*
- The symbol SO_OOBINLINE is not known to Ultrix 2.0.
- It means "leave out of band data inline". The normal value is 0x0100,
- but don't try this on systems where the symbol is undefined.
- */
- /*
- Note from Jeff Altman: 12/13/95
- In implementing rlogin protocol I have come to the conclusion that it is
- a really bad idea to read out-of-band data inline.
- At least Windows and OS/2 does not handle this well.
- And if you need to know that data is out-of-band, then it becomes
- absolutely pointless.
- Therefore, at least on OS2 and Windows (NT) I have changed the value of
- on to 0, so that out-of-band data stays out-of-band.
- 12/18/95
- Actually, OOB data should be read inline when possible. Especially with
- protocols that don't care about the Urgent flag. This is true with Telnet.
- With Rlogin, you need to be able to catch OOB data. However, the best
- way to do this is to set a signal handler on SIGURG. This isn't possible
- on OS/2 and Windows. But it is in UNIX. We will also need OOB data for
- FTP so better create a general mechanism.
- The reason for making OOB data be inline is that the standard ttinc/ttoc
- calls can be used for reading that data on UNIX systems. If we didn't
- have the OOBINLINE option set then we would have to use recv(,MSG_OOB)
- to read it.
- */
- #ifdef RLOGCODE
- #ifdef TCPIPLIB
- if (ttnproto == NP_RLOGIN
- #ifdef CK_KERBEROS
- || ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN
- || ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN
- #endif /* CK_KERBEROS */
- )
- on = 0;
- #else /* TCPIPLIB */
- if (ttnproto == NP_RLOGIN
- #ifdef CK_KERBEROS
- || ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN
- || ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN
- #endif /* CK_KERBEROS */
- ) {
- debug(F100,"Installing rlogoobh on SIGURG","",0);
- signal(SIGURG, rlogoobh);
- on = 0;
- } else {
- debug(F100,"Ignoring SIGURG","",0);
- signal(SIGURG, SIG_DFL);
- }
- #endif /* TCPIPLIB */
- #endif /* RLOGCODE */
- #ifdef datageneral
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef BSD43
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef OSF1
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef POSIX
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef MOTSV88R4
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef SOLARIS
- /*
- Maybe this applies to all SVR4 versions, but the other (else) way has been
- compiling and working fine on all the others, so best not to change it.
- */
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef OSK
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef OS2
- {
- int rc;
- rc = setsockopt(ttyfd,
- SOL_SOCKET,
- SO_OOBINLINE,
- (char *) &on,
- sizeof on
- );
- debug(F111,"setsockopt SO_OOBINLINE",on ? "on" : "off" ,rc);
- }
- #else
- #ifdef VMS /* or, at least, VMS with gcc */
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef CLIX
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
- #endif /* CLIX */
- #endif /* VMS */
- #endif /* OS2 */
- #endif /* OSK */
- #endif /* SOLARIS */
- #endif /* MOTSV88R4 */
- #endif /* POSIX */
- #endif /* BSD43 */
- #endif /* OSF1 */
- #endif /* datageneral */
- #endif /* SO_OOBINLINE */
- #ifndef NOTCPOPTS
- #ifndef datageneral
- #ifdef SOL_SOCKET
- #ifdef TCP_NODELAY
- no_delay(ttyfd,tcp_nodelay);
- #endif /* TCP_NODELAY */
- #ifdef SO_KEEPALIVE
- keepalive(ttyfd,tcp_keepalive);
- #endif /* SO_KEEPALIVE */
- #ifdef SO_LINGER
- ck_linger(ttyfd,tcp_linger, tcp_linger_tmo);
- #endif /* SO_LINGER */
- #ifdef SO_SNDBUF
- sendbuf(ttyfd,tcp_sendbuf);
- #endif /* SO_SNDBUF */
- #ifdef SO_RCVBUF
- recvbuf(ttyfd,tcp_recvbuf);
- #endif /* SO_RCVBUF */
- #endif /* SOL_SOCKET */
- #endif /* datageneral */
- #endif /* NOTCPOPTS */
- #ifndef datageneral
- /* Find out our own IP address. */
- /* We need the l_addr structure for [E]KLOGIN. */
- l_slen = sizeof(l_addr);
- bzero((char *)&l_addr, l_slen);
- #ifndef EXCELAN
- if (!getsockname(ttyfd, (struct sockaddr *)&l_addr, &l_slen)) {
- char * s = (char *)inet_ntoa(l_addr.sin_addr);
- ckstrncpy(myipaddr, s, 20);
- debug(F110,"getsockname",myipaddr,0);
- }
- #endif /* EXCELAN */
- #endif /* datageneral */
- /*
- This is really only needed for Kerberos IV but is useful information in any
- case. If we connect to a name that is really a pool, we need to get the
- name of the machine we are actually connecting to for K4 to authenticate
- properly. This way we also update the names properly.
- However, it is a security hole when used with insecure DNS.
- Note: This does not work on Windows 95 or Windows NT 3.5x. This is because
- of the Microsoft implementation of gethostbyaddr() in both Winsock 1.1
- and Winsock 2.0 on those platforms. Their algorithm is:
- 1. Check the HOSTENT cache.
- 2. Check the HOSTS file at %SystemRoot%\System32\DRIVERS\ETC.
- 3. Do a DNS query if the DNS server is configured for name resolution.
- 4. Do an additional NetBIOS remote adapter status to an IP address for its
- NetBIOS name table. This step is specific only to the Windows NT version
- 3.51 implementation.
- The problem is the use of the HOSTENT cache. It means that gethostbyaddr()
- can not be used to resolve the real name of machine if it was originally
- accessed by an alias used to represent a cluster.
- */
- if ((tcp_rdns && dns || tcp_rdns == SET_ON
- #ifdef CK_KERBEROS
- || tcp_rdns == SET_AUTO &&
- (ck_krb5_is_installed() || ck_krb4_is_installed())
- #endif /* CK_KERBEROS */
- )
- #ifndef NOHTTP
- && (tcp_http_proxy == NULL)
- #endif /* NOHTTP */
- #ifdef CK_SSL
- && !(ssl_only_flag || tls_only_flag)
- #endif /* CK_SSL */
- ) {
- #ifdef NT
- if (isWin95())
- sleep(1);
- #endif /* NT */
- if (!quiet) {
- printf(" Reverse DNS Lookup... ");
- fflush(stdout);
- }
- if (host = gethostbyaddr((char *)&r_addr.sin_addr,4,PF_INET)) {
- char * s;
- host = ck_copyhostent(host);
- debug(F100,"netopen gethostbyname != NULL","",0);
- if (!quiet) {
- printf("(OK)\n");
- fflush(stdout);
- }
- s = host->h_name;
- if (!s) { /* This can happen... */
- debug(F100,"netopen host->h_name is NULL","",0);
- s = "";
- }
- /* Something is wrong with inet_ntoa() on HPUX 10.xx */
- /* The compiler says "Integral value implicitly converted to */
- /* pointer in assignment." The prototype is right there */
- /* in <arpa/inet.h> so what's the problem? */
- /* Ditto in HP-UX 5.x, but not 8.x or 9.x... */
- if (!*s) { /* No name so substitute the address */
- debug(F100,"netopen host->h_name is empty","",0);
- s = inet_ntoa(r_addr.sin_addr); /* Convert address to string */
- if (!s) /* Trust No 1 */
- s = "";
- if (*s) { /* If it worked, use this string */
- ckstrncpy(ipaddr,s,20);
- }
- s = ipaddr; /* Otherwise stick with the IP */
- if (!*s) /* or failing that */
- s = namecopy; /* the name we were called with. */
- }
- if (*s) { /* Copying into our argument? */
- ckstrncpy(name,s,80); /* Bad Bad Bad */
- if ( (80-strlen(name)) > (strlen(svcbuf)+1) ) {
- ckstrncat(name,":",80-strlen(name));
- ckstrncat(name,svcbuf,80-strlen(name));
- }
- }
- if (!quiet && *s
- #ifndef NOICP
- && !doconx
- #endif /* NOICP */
- ) {
- printf(" %s connected on port %s\n",s,p);
- #ifdef BETADEBUG
- /* This is simply for testing the DNS entries */
- if (host->h_aliases) {
- char ** a = host->h_aliases;
- while (*a) {
- printf(" alias => %s\n",*a);
- a++;
- }
- }
- #endif /* BETADEBUG */
- }
- } else {
- if (!quiet) printf("Failed.\n");
- }
- } else if (!quiet) printf("(OK)\n");
- if (!quiet) fflush(stdout);
- /* This should already have been done but just in case */
- ckstrncpy(ipaddr,(char *)inet_ntoa(r_addr.sin_addr),20);
- #ifdef CK_SECURITY
- /* Before Initialization Telnet/Rlogin Negotiations Init Kerberos */
- #ifndef NOHTTP
- if (tcp_http_proxy) {
- for (i=strlen(proxycopy); i >= 0 ; i--)
- if ( proxycopy[i] == ':' )
- proxycopy[i] = '\0';
- }
- #endif /* NOHTTP */
- ck_auth_init(
- #ifndef NOHTTP
- tcp_http_proxy ? proxycopy :
- #endif /* NOHTTP */
- (tcp_rdns && host && host->h_name && host->h_name[0]) ?
- (char *)host->h_name : (namecopy2[0] ? namecopy2 :
- (namecopy[0] ? namecopy : ipaddr)),
- ipaddr,
- uidbuf,
- ttyfd
- );
- #endif /* CK_SECURITY */
- #ifdef CK_SSL
- if (ck_ssleay_is_installed()) {
- if (!ssl_tn_init(SSL_CLIENT)) {
- debug(F100,"netopen ssl_tn_init() failed","",0);
- if (bio_err!=NULL) {
- BIO_printf(bio_err,"ssl_tn_init() failed\n");
- ERR_print_errors(bio_err);
- } else {
- fflush(stderr);
- fprintf(stderr,"ssl_tn_init() failed\n");
- ERR_print_errors_fp(stderr);
- }
- if (tls_only_flag || ssl_only_flag) {
- debug(F100,"netopen ssl/tls required","",0);
- netclos();
- return(-1);
- }
- /* we will continue to accept the connection */
- /* without SSL or TLS support unless required. */
- if ( TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) != TN_NG_MU )
- TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
- if ( TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) != TN_NG_MU )
- TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
- if ( TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) != TN_NG_MU )
- TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
- if ( TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) != TN_NG_MU )
- TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
- } else if ( ck_ssl_outgoing(ttyfd) < 0 ) {
- debug(F100,"ck_ssl_outgoing() failed","",0);
- netclos();
- return(-1);
- }
- }
- #endif /* CK_SSL */
- #ifdef RLOGCODE
- if (ttnproto == NP_RLOGIN
- #ifdef CK_KERBEROS
- || ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN
- || ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN
- #endif /* CK_KERBEROS */
- ) { /* Similar deal for rlogin */
- if (rlog_ini(((tcp_rdns && host && host->h_name && host->h_name[0]) ?
- (CHAR *)host->h_name : (CHAR *)ipaddr),
- service->s_port,
- &l_addr,&r_addr
- ) < 0) {
- debug(F100,"rlogin initialization failed","",0);
- netclos();
- return(-1);
- }
- } else
- #endif /* RLOGCODE */
- if (tn_ini() < 0) { /* Start Telnet negotiations. */
- netclos();
- return(-1); /* Gone, so open failed. */
- }
- if (ttchk() < 0) {
- netclos();
- return(-1);
- }
- #ifdef CK_KERBEROS
- #ifdef KRB5_U2U
- if ( ttnproto == NP_K5U2U ) {
- if (k5_user_to_user_client_auth()) {
- netclos();
- return(-1);
- }
- }
- #endif /* KRB5_U2U */
- #endif /* CK_KERBEROS */
- debug(F101,"netopen service","",svcnum);
- debug(F110,"netopen name",name,0);
- debug(F110,"netopen ipaddr",ipaddr,0);
- ckstrncpy(hostipaddr,ipaddr,63);
- if (lcl) if (*lcl < 0) /* Local mode. */
- *lcl = 1;
- #endif /* TCPSOCKET */
- return(0); /* Done. */
- }
- /* N E T C L O S -- Close current network connection. */
- #ifndef NOLOCAL
- _PROTOTYP(VOID slrestor,(VOID));
- #ifdef CK_SSL
- int tls_norestore = 0;
- #endif /* CK_SSL */
- #endif /* NOLOCAL */
- int
- netclos() {
- static int close_in_progress = 0;
- int x = 0, y, z;
- debug(F101,"netclos","",ttyfd);
- #ifdef NETLEBUF
- if (!tt_push_inited)
- le_init();
- #endif /* NETLEBUF */
- if (ttyfd == -1) /* Was open? */
- return(0); /* Wasn't. */
- if (close_in_progress)
- return(0);
- close_in_progress = 1; /* Remember */
- #ifndef NOLOCAL
- /* This function call should not be here since this is a direct call */
- /* from an I/O routine to a user interface level function. However, */
- /* the reality is that we do not have pure interfaces. If we ever */
- /* decide to clean this up the UI level should assign this function */
- /* via a pointer assignment. - Jeff 9/10/1999 */
- #ifdef CK_SSL
- if (!tls_norestore)
- #endif /* CK_SSL */
- slrestor();
- #endif /* NOLOCAL */
- #ifdef OS2
- RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
- #else /* OS2 */
- if (ttyfd > -1) /* Was. */
- #endif /* OS2 */
- {
- #ifdef VMS
- y = 1; /* Turn on nonblocking reads */
- z = socket_ioctl(ttyfd,FIONBIO,&y);
- debug(F111,"netclos FIONBIO","on",z);
- #endif /* VMS */
- #ifdef TNCODE
- if (ttnproto == NP_TELNET) {
- if (!TELOPT_ME(TELOPT_LOGOUT)
- #ifdef COMMENT
- /* Jeff 2005/12/30 */
- #ifdef CK_SSL
- && !ssl_raw_flag && !tls_raw_flag
- #endif /* CK_SSL */
- #endif /* COMMENT */
- ) {
- /* Send LOGOUT option before close */
- if (tn_sopt(DO,TELOPT_LOGOUT) >= 0) {
- TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
- /* It would be nice to call tn_wait but we can't */
- }
- }
- tn_push(); /* Place any waiting data into input*/
- }
- #endif /* TNCODE */
- #ifdef CK_SSL
- if (ssl_active_flag) {
- if (ssl_debug_flag)
- BIO_printf(bio_err,"calling SSL_shutdown\n");
- SSL_shutdown(ssl_con);
- ssl_active_flag = 0;
- }
- if (tls_active_flag) {
- if (ssl_debug_flag)
- BIO_printf(bio_err,"calling SSL_shutdown\n");
- SSL_shutdown(tls_con);
- tls_active_flag = 0;
- }
- #endif /* CK_SSL */
- #ifdef VMS
- ck_cancio(); /* Cancel any outstanding reads. */
- #endif /* VMS */
- #ifdef TCPIPLIB
- x = socket_close(ttyfd); /* Close it. */
- #else
- #ifndef OS2
- #ifdef IBMX25
- if (ttnet == NET_IX25) {
- /* riehm: should send a disc_req - but only if link is still OK */
- x = x25clear();
- close(ttyfd);
- if (x25serverfd) {
- /* we were the passive client of a server, now we
- * go back to being the normal client.
- * I hope that kermit can cope with the logic that
- * there can still be a connection after netclos
- * has been called.
- */
- ttyfd = x25serverfd;
- x25serverfd = 0;
- /*
- * need to close the server connection too - because
- * all file descriptors connected to the NPI have the
- * same status.
- *
- * The problem is that any waiting connections get
- * lost, the client doesn't realise, and hangs.
- */
- netclos();
- }
- x25_state = X25_CLOSED; /* riehm: dead code? */
- } else
- #endif /* IBMX25 */
- x = close(ttyfd);
- #endif /* OS2 */
- #endif /* TCPIPLIB */
- }
- ttyfd = -1; /* Mark it as closed. */
- wasclosed = 1;
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- #ifdef TNCODE
- #ifdef CK_FORWARD_X
- fwdx_close_all(); /* Shut down any Forward X sockets */
- #endif /* CK_FORWARD_X */
- tn_reset(); /* The Reset Telnet Option table. */
- debug(F100,"netclose setting tn_init = 0","",0);
- tn_init = 0; /* Remember about telnet protocol... */
- sstelnet = 0; /* Client-side Telnet */
- #endif /* TNCODE */
- *ipaddr = '\0'; /* Zero the IP address string */
- tcp_incoming = 0; /* No longer incoming */
- /* Don't reset ttnproto so that we can remember which protocol is in use */
- #ifdef TCPIPLIB
- /*
- Empty the internal buffers so they won't be used as invalid input on
- the next connect attempt (rlogin).
- */
- ttibp = 0;
- ttibn = 0;
- #endif /* TCPIPLIB */
- #ifdef CK_KERBEROS
- /* If we are automatically destroying Kerberos credentials on Close */
- /* do it now. */
- #ifdef KRB4
- if (krb4_autodel == KRB_DEL_CL) {
- extern struct krb_op_data krb_op;
- krb_op.version = 4;
- krb_op.cache = NULL;
- ck_krb4_destroy(&krb_op);
- }
- #endif /* KRB4 */
- #ifdef KRB5
- if (krb5_autodel == KRB_DEL_CL) {
- extern struct krb_op_data krb_op;
- extern char * krb5_d_cc;
- krb_op.version = 5;
- krb_op.cache = krb5_d_cc;
- ck_krb5_destroy(&krb_op);
- }
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- close_in_progress = 0; /* Remember we are done. */
- return(x);
- }
- #ifdef OS2
- int
- os2socketerror( int s_errno ) {
- #ifdef OS2ONLY
- if (s_errno > 0 && s_errno <= SOCBASEERR) {
- /* in OS/2, there is a problem with threading in that
- * the value of errno is not thread safe. It can be
- * set to a value from a previous library call and if
- * it was not cleared it will appear here. Only treat
- * valid socket error codes as errors in this function.
- */
- debug(F100,"os2socketerror errno.h","",0);
- socket_errno = 0;
- return(0);
- }
- #endif /* OS2ONLY */
- switch (s_errno) {
- case 0: /* NO ERROR */
- debug(F100,"os2socketerror NOERROR","",0);
- return(0);
- #ifdef NT
- case WSAECONNRESET:
- #else /* NT */
- case SOCECONNRESET:
- case SOCECONNRESET - SOCBASEERR:
- #endif /* NT */
- debug(F100,"os2socketerror ECONRESET","",0);
- tn_debug("ECONRESET");
- netclos(); /* *** *** */
- return(-1); /* Connection is broken. */
- #ifdef NT
- case WSAECONNABORTED:
- #else /* NT */
- case SOCECONNABORTED:
- case SOCECONNABORTED - SOCBASEERR:
- #endif /* NT */
- debug(F100,"os2socketerror ECONNABORTED","",0);
- tn_debug("ECONNABORTED");
- netclos(); /* *** *** */
- return(-1); /* Connection is broken. */
- #ifdef NT
- case WSAENETRESET:
- #else /* NT */
- case SOCENETRESET:
- case SOCENETRESET - SOCBASEERR:
- #endif /* NT */
- debug(F100,"os2socketerror ENETRESET","",0);
- tn_debug("ENETRESET");
- netclos(); /* *** *** */
- return(-1); /* Connection is broken. */
- #ifdef NT
- case WSAENOTCONN:
- #else /* NT */
- case SOCENOTCONN:
- case SOCENOTCONN - SOCBASEERR:
- #endif /* NT */
- debug(F100,"os2socketerror ENOTCONN","",0);
- tn_debug("ENOTCONN");
- netclos(); /* *** *** */
- return(-1); /* Connection is broken. */
- #ifdef NT
- case WSAESHUTDOWN:
- debug(F100,"os2socketerror ESHUTDOWN","",0);
- tn_debug("ESHUTDOWN");
- netclos(); /* *** *** */
- return(-1); /* Connection is broken. */
- #endif /* NT */
- #ifdef NT
- case WSAEWOULDBLOCK:
- #else
- case SOCEWOULDBLOCK:
- case SOCEWOULDBLOCK - SOCBASEERR:
- #endif /* NT */
- debug(F100,"os2socketerror EWOULDBLOCK","",0);
- return(0);
- #ifdef NT
- case ERROR_IO_INCOMPLETE:
- case ERROR_IO_PENDING:
- case ERROR_OPERATION_ABORTED:
- return(0);
- #endif /* NT */
- default:
- return(-2);
- }
- return(0);
- }
- #endif /* OS2 */
- /* N E T T C H K -- Check if network up, and how many bytes can be read */
- /*
- Returns number of bytes waiting, or -1 if connection has been dropped.
- */
- int /* Check how many bytes are ready */
- nettchk() { /* for reading from network */
- #ifdef TCPIPLIB
- long count = 0;
- int x = 0, z;
- long y;
- char c;
- int rc;
- #ifdef NT
- extern int ionoblock; /* For Overlapped I/O */
- #endif /* NT */
- debug(F101,"nettchk entry ttibn","",ttibn);
- debug(F101,"nettchk entry ttibp","",ttibp);
- #ifdef NETLEBUF
- {
- int n = 0;
- if (ttpush >= 0)
- n++;
- n += le_inbuf();
- if (n > 0)
- return(n);
- }
- #endif /* NETLEBUF */
- #ifndef OS2
- #ifndef BEBOX
- socket_errno = 0; /* This is a function call in NT, and BeOS */
- #endif /* BEBOX */
- #endif /* OS2 */
- if (ttyfd == -1) {
- debug(F100,"nettchk socket is closed","",0);
- return(-1);
- }
- /*
- Note: this socket_ioctl() call does NOT return an error if the
- connection has been broken. (At least not in MultiNet.)
- */
- #ifdef COMMENT
- /* Another trick that can be tried here is something like this: */
- if (ttnet == NET_TCPB) {
- char dummy;
- x = read(ttyfd,&dummy,0); /* Try to read nothing */
- if (x < 0) { /* "Connection reset by peer" */
- perror("TCP/IP"); /* or somesuch... */
- ttclos(0); /* Close our end too. */
- return(-1);
- }
- }
- #endif /* COMMENT */
- #ifdef CK_SSL
- if (ssl_active_flag) {
- #ifndef IKSDONLY
- #ifdef OS2
- if ( IsConnectMode() ) {
- debug(F101,"nettchk (ssl_active_flag) returns","",count);
- return(0);
- }
- #endif /* OS2 */
- #endif /* IKSDONLY */
- count = SSL_pending(ssl_con);
- if (count < 0) {
- debug(F111,"nettchk","SSL_pending error",count);
- netclos();
- return(-1);
- }
- if ( count > 0 )
- return(count); /* Don't perform a read */
- } else if (tls_active_flag) {
- #ifndef IKSDONLY
- #ifdef OS2
- if ( IsConnectMode() ) {
- debug(F101,"nettchk (tls_active_flag) returns","",count);
- return(0);
- }
- #endif /* OS2 */
- #endif /* IKSDONLY */
- count = SSL_pending(tls_con);
- if (count < 0) {
- debug(F111,"nettchk","TLS_pending error",count);
- netclos();
- return(-1);
- }
- if ( count > 0 )
- return(count); /* Don't perform a read */
- } else
- #endif /* CK_SSL */
- if (socket_ioctl(ttyfd,FIONREAD,
- #ifdef COMMENT
- /* Now we've changed the ioctl(..,..,x) prototype for DECC to (void *) */
- #ifdef __DECC
- /* NOTE: "&count" might need to be "(char *)&count" in some settings. */
- /* Cast needed for DECC 4.1 & later? */
- /* Maybe, but __DECC_VER only exists in 5.0 and later */
- (char *)
- #endif /* __DECC */
- #endif /* COMMENT */
- &count
- ) < 0) {
- debug(F101,"nettchk socket_ioctl error","",socket_errno);
- /* If the connection is gone, the connection is gone. */
- netclos();
- #ifdef NT_TCP_OVERLAPPED
- /* Is there anything in the overlapped I/O buffers? */
- count += OverlappedDataWaiting();
- #endif /* NT_TCP_OVERLAPPED */
- count += ttibn;
- return(count>0?count:-1);
- }
- debug(F101,"nettchk count","",count);
- #ifdef NT_TCP_OVERLAPPED
- /* Is there anything in the overlapped I/O buffers? */
- count += OverlappedDataWaiting();
- debug(F101,"nettchk count w/overlapped","",count);
- #endif /* NT_TCP_OVERLAPPED */
- #ifdef OS2
- #ifndef IKSDONLY
- if ( IsConnectMode() ) {
- debug(F101,"nettchk (FIONREAD) returns","",count);
- return(count);
- }
- #endif /* IKSDONLY */
- #endif /* OS2 */
- /* For the sake of efficiency, if there is still data in the ttibuf */
- /* do not go to the bother of checking to see of the connection is */
- /* still valid. The handle is still good, so just return the count */
- /* of the bytes that we already have left to process. */
- #ifdef OS2
- if ( count > 0 || ttibn > 0 ) {
- count+=ttibn;
- debug(F101,"nettchk (count+ttibn > 0) returns","",count);
- return(count);
- } else {
- RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
- if ( ttibn == 0 )
- ttibp = 0; /* reset for next read */
- }
- #else /* OS2 */
- if ( count > 0 || ttibn > 0 ) {
- debug(F101,"nettchk returns","",count+ttibn);
- return(count+ttibn);
- }
- ttibn = ttibp = 0;
- #endif /* OS2 */
- /*
- The following code works well in most settings, but messes things up in
- others, including CMU/Tek TCP/IP and UCX 2.0, where it somehow manages to
- make it impossible to ever make a new connection to the same host again with
- CONNECT, once it has been logged out from the first time. Not even if you
- HANGUP first, or SET HOST<CR>, or SET LINE<CR>. Reportedly, however, it
- does work OK in later releases of UCX. But there is no way we can
- accommodate both old and new -- we might have static linking or dynamic
- linking, etc etc. If we have static, I only have access to 2.0, where this
- doesn't work, etc etc blah blah.
- In the following lines, we define a symbol NOCOUNT for builds where we want
- to omit this code. By default, it is omitted for CMU/Tek. You can force
- omission of it for other combinations by defining NOCOUNT in CFLAGS. You
- can force inclusion of this code, even for CMU/Tek, by including NONOCOUNT
- in CFLAGS.
- */
- #ifdef NONOCOUNT
- #ifdef NOCOUNT
- #undef NOCOUNT
- #endif /* NOCOUNT */
- #else
- #ifndef NOCOUNT
- #ifdef CMU_TCPIP
- #define NOCOUNT
- #endif /* CMU_TCPIP */
- #endif /* NOCOUNT */
- #endif /* NONOCOUNT */
- /* From this point forward we have a possible race condition in K95
- * due to its use of multiple threads. Therefore, we must ensure
- * that only one thread attempt to read/write from the socket at a
- * time. Otherwise, it is possible for a buffer to be overwritten.
- */
- /* we know now that count >= 0 and that ttibn == 0 */
- if (count == 0
- #ifdef RLOGCODE
- #ifdef CK_KERBEROS
- && ttnproto != NP_EK4LOGIN && ttnproto != NP_EK5LOGIN
- #endif /* CK_KERBEROS */
- #endif /* RLOGCODE */
- ) {
- int s_errno = 0;
- #ifndef NOCOUNT
- /*
- Here we need to tell the difference between a 0 count on an active
- connection, and a 0 count because the remote end of the socket broke the
- connection. There is no mechanism in TGV MultiNet (or WIN/TCP?) to query
- the status of the connection, so we have to do a read. -1 means there was
- no data available (socket_errno == EWOULDBLOCK), 0 means the connection is
- down. But if, by chance, we actually get a character, we have to put it
- where it won't be lost.
- */
- #ifndef NON_BLOCK_IO
- #ifdef OS2
- #ifdef CK_SSL
- RequestSSLMutex(SEM_INDEFINITE_WAIT);
- #endif /* CK_SSL */
- #endif /* OS2 */
- y = 1; /* Turn on nonblocking reads */
- z = socket_ioctl(ttyfd,FIONBIO,&y);
- debug(F111,"nettchk FIONBIO","on",z);
- #ifdef OS2
- #ifdef CK_SSL
- ReleaseSSLMutex();
- #endif /* CK_SSL */
- #endif /* OS2 */
- #endif /* NON_BLOCK_IO */
- #ifdef NT_TCP_OVERLAPPED
- ionoblock = 1; /* For Overlapped I/O */
- #endif /* NT_TCP_OVERLAPPED */
- #ifdef CK_SSL
- if ( ssl_active_flag || tls_active_flag ) {
- #ifdef OS2
- ssl_read:
- x = SSL_read( ssl_active_flag?ssl_con:tls_con,
- &ttibuf[ttibp+ttibn],
- TTIBUFL-ttibp-ttibn );
- switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
- case SSL_ERROR_NONE:
- debug(F111,"nettchk SSL_ERROR_NONE","x",x);
- break;
- case SSL_ERROR_WANT_WRITE:
- debug(F100,"nettchk SSL_ERROR_WANT_WRITE","",0);
- x = -1;
- break;
- case SSL_ERROR_WANT_READ:
- debug(F100,"nettchk SSL_ERROR_WANT_READ","",0);
- x = -1;
- break;
- case SSL_ERROR_SYSCALL:
- if ( x == 0 ) { /* EOF */
- netclos();
- rc = -1;
- goto nettchk_return;
- } else {
- #ifdef NT
- int gle = GetLastError();
- #endif /* NT */
- #ifndef NON_BLOCK_IO
- #ifdef OS2
- #ifdef CK_SSL
- RequestSSLMutex(SEM_INDEFINITE_WAIT);
- #endif /* CK_SSL */
- #endif /* OS2 */
- y = 0; /* Turn off nonblocking reads */
- z = socket_ioctl(ttyfd,FIONBIO,&y);
- debug(F111,"nettchk FIONBIO","off",z);
- #ifdef OS2
- #ifdef CK_SSL
- ReleaseSSLMutex();
- #endif /* CK_SSL */
- #endif /* OS2 */
- #endif /* NON_BLOCK_IO */
- #ifdef NT_TCP_OVERLAPPED
- ionoblock = 0; /* For Overlapped I/O */
- #endif /* NT_TCP_OVERLAPPED */
- #ifdef NT
- debug(F111,"nettchk SSL_ERROR_SYSCALL",
- "GetLastError()",gle);
- rc = os2socketerror(gle);
- if (rc == -1)
- rc = -2;
- else if ( rc == -2 )
- rc = -1;
- goto nettchk_return;
- #endif /* NT */
- break;
- }
- case SSL_ERROR_WANT_X509_LOOKUP:
- debug(F100,"nettchk SSL_ERROR_WANT_X509_LOOKUP","",0);
- break;
- case SSL_ERROR_SSL:
- if (bio_err!=NULL) {
- int len;
- extern char ssl_err[];
- BIO_printf(bio_err,"nettchk() SSL_ERROR_SSL\n");
- ERR_print_errors(bio_err);
- len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
- ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
- debug(F110,"nettchk SSL_ERROR_SSL",ssl_err,0);
- if (ssl_debug_flag)
- printf(ssl_err);
- } else if (ssl_debug_flag) {
- debug(F100,"nettchk SSL_ERROR_SSL","",0);
- fflush(stderr);
- fprintf(stderr,"nettchk() SSL_ERROR_SSL\n");
- ERR_print_errors_fp(stderr);
- }
- #ifdef COMMENT
- netclos();
- rc = -1;
- goto nettchk_return;
- #else
- x = -1;
- break;
- #endif
- case SSL_ERROR_ZERO_RETURN:
- debug(F100,"nettchk SSL_ERROR_ZERO_RETURN","",0);
- netclos();
- rc = -1;
- goto nettchk_return;
- default:
- debug(F100,"nettchk SSL_ERROR_?????","",0);
- netclos();
- rc = -1;
- goto nettchk_return;
- }
- #else /* OS2 */
- /* Do not block */
- x = -1;
- #endif /* OS2 */
- } else
- #endif /* CK_SSL */
- {
- #ifdef OS2
- x = socket_read(ttyfd,&ttibuf[ttibp+ttibn],
- TTIBUFL-ttibp-ttibn); /* Returns -1 if no data */
- #else /* OS2 */
- x = socket_read(ttyfd,&c,1); /* Returns -1 if no data */
- #endif /* OS2 */
- }
- s_errno = socket_errno; /* socket_errno may be a function */
- debug(F101,"nettchk socket_read","",x);
- #ifndef NON_BLOCK_IO
- #ifdef OS2
- #ifdef CK_SSL
- RequestSSLMutex(SEM_INDEFINITE_WAIT);
- #endif /* CK_SSL */
- #endif /* OS2 */
- y = 0; /* Turn off nonblocking reads */
- z = socket_ioctl(ttyfd,FIONBIO,&y);
- debug(F111,"nettchk FIONBIO","off",z);
- #ifdef OS2
- #ifdef CK_SSL
- ReleaseSSLMutex();
- #endif /* CK_SSL */
- #endif /* OS2 */
- #endif /* NON_BLOCK_IO */
- #ifdef NT_TCP_OVERLAPPED
- ionoblock = 0; /* For Overlapped I/O */
- #endif /* NT_TCP_OVERLAPPED */
- if (x == -1) {
- debug(F101,"nettchk socket_read errno","",s_errno);
- #ifdef OS2
- if (os2socketerror(s_errno) < 0) {
- rc = -1;
- goto nettchk_return;
- }
- #endif /* OS2 */
- } else if (x == 0) {
- debug(F100,"nettchk connection closed","",0);
- netclos(); /* *** *** */
- rc = -1;
- goto nettchk_return;
- }
- if (x >= 1) { /* Oops, actually got a byte? */
- #ifdef OS2
- /* In OS/2 we read directly into ttibuf[] */
- ckhexdump("nettchk got real data",&ttibuf[ttibp+ttibn],x);
- ttibn += x;
- #else /* OS2 */
- #ifdef CK_SSL
- if ( ssl_active_flag || tls_active_flag ) {
- ckhexdump("nettchk got real data",&ttibuf[ttibp+ttibn],x);
- ttibn += x;
- } else
- #endif /* CK_SSL */
- {
- debug(F101,"nettchk socket_read char","",c);
- debug(F101,"nettchk ttibp","",ttibp);
- debug(F101,"nettchk ttibn","",ttibn);
- /*
- In the case of Overlapped I/O the character would have come from
- the beginning of the buffer, so put it back.
- */
- if (ttibp > 0) {
- ttibp--;
- ttibuf[ttibp] = c;
- ttibn++;
- } else {
- ttibuf[ttibp+ttibn] = c;
- ttibn++;
- }
- }
- #endif /* OS2 */
- }
- #else /* NOCOUNT */
- if (ttnet == NET_TCPB) {
- char dummy;
- x = read(ttyfd,&dummy,0); /* Try to read nothing */
- if (x < 0) { /* "Connection reset by peer" */
- perror("TCP/IP"); /* or somesuch... */
- ttclos(0); /* Close our end too. */
- rc = -1;
- goto nettchk_return;
- }
- }
- #endif /* NOCOUNT */
- }
- #ifdef CK_KERBEROS
- #ifdef KRB4
- #ifdef RLOGCODE
- if (ttnproto == NP_EK4LOGIN)
- count += krb4_des_avail(ttyfd);
- #endif /* RLOGCODE */
- #endif /* KRB4 */
- #ifdef KRB5
- #ifdef RLOGCODE
- if (ttnproto == NP_EK5LOGIN)
- count += krb5_des_avail(ttyfd);
- #endif /* RLOGCODE */
- #ifdef KRB5_U2U
- if (ttnproto == NP_K5U2U)
- count += krb5_u2u_avail(ttyfd);
- #endif /* KRB5_U2U */
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- debug(F101,"nettchk returns","",count+ttibn);
- rc = count + ttibn;
- nettchk_return:
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(rc);
- #else /* Not TCPIPLIB */
- /*
- UNIX just uses ttchk(), in which the ioctl() calls on the file descriptor
- seem to work OK.
- */
- return(ttchk());
- #endif /* TCPIPLIB */
- /*
- But what about X.25?
- */
- }
- #ifndef OS2
- VOID
- nettout(i) int i; { /* Catch the alarm interrupts */
- debug(F100,"nettout caught timeout","",0);
- ttimoff();
- cklongjmp(njbuf, -1);
- }
- #endif /* !OS2 */
- #ifdef TCPIPLIB
- VOID
- #ifdef CK_ANSIC
- donetinc(void * threadinfo)
- #else /* CK_ANSIC */
- donetinc(threadinfo) VOID * threadinfo;
- #endif /* CK_ANSIC */
- /* donetinc */ {
- #ifdef NTSIG
- extern int TlsIndex;
- setint();
- if (threadinfo) { /* Thread local storage... */
- TlsSetValue(TlsIndex,threadinfo);
- }
- #endif /* NTSIG */
- #ifdef CK_LOGIN
- #ifdef NT
- #ifdef IKSD
- if (inserver)
- setntcreds();
- #endif /* IKSD */
- #endif /* NT */
- #endif /* CK_LOGIN */
- while (1) {
- if (ttbufr() < 0) /* Keep trying to refill it. */
- break; /* Till we get an error. */
- if (ttibn > 0) /* Or we get a character. */
- break;
- }
- }
- #endif /* TCPIPLIB */
- VOID
- #ifdef CK_ANSIC
- failnetinc(void * threadinfo)
- #else /* CK_ANSIC */
- failnetinc(threadinfo) VOID * threadinfo;
- #endif /* CK_ANSIC */
- /* failnetinc */ {
- ; /* Nothing to do on an error */
- }
- /* N E T X I N -- Input block of characters from network */
- int
- netxin(n,buf) int n; CHAR * buf; {
- int len, i, j;
- #ifdef TCPIPLIB
- int rc;
- #endif /* TCPIPLIB */
- if (ttyfd == -1) {
- debug(F100,"netxin socket is closed","",0);
- return(-2);
- }
- #ifdef CK_KERBEROS
- #ifdef KRB4
- #ifdef RLOGCODE
- if (ttnproto == NP_EK4LOGIN) {
- if ((len = krb4_des_read(ttyfd,buf,n)) < 0)
- return(-1);
- else
- return(len);
- }
- #endif /* RLOGCODE */
- #endif /* KRB4 */
- #ifdef KRB5
- #ifdef RLOGCODE
- if (ttnproto == NP_EK5LOGIN) {
- if ((len = krb5_des_read(ttyfd,(char *)buf,n,0)) < 0)
- return(-1);
- else
- return(len);
- }
- #endif /* RLOGCODE */
- #ifdef KRB5_U2U
- if (ttnproto == NP_K5U2U) {
- if ((len = krb5_u2u_read(ttyfd,(char *)buf,n)) < 0)
- return(-1);
- else
- return(len);
- }
- #endif /* KRB5_U2U */
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- #ifdef TCPIPLIB
- #ifdef OS2
- RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
- #endif /* OS2 */
- if (ttibn == 0)
- if ((rc = ttbufr()) <= 0) {
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(rc);
- }
- if (ttibn <= n) {
- len = ttibn;
- memcpy(buf,&ttibuf[ttibp],len); /* safe */
- ttibp += len;
- ttibn = 0;
- } else {
- memcpy(buf,&ttibuf[ttibp],n); /* safe */
- ttibp += n;
- ttibn -= n;
- len = n;
- }
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- #else /* TCPIPLIB */
- for (i = 0; i < n; i++) {
- if ((j = netinc(0)) < 0) {
- if (j < -1)
- return(j);
- else
- break;
- }
- buf[i] = j;
- }
- len = i;
- #endif /* TCPIPLIB */
- #ifdef COMMENT
- #ifdef CK_ENCRYPTION
- /* This would be great if it worked. But what if the buffer we read */
- /* contains a telnet negotiation that changes the state of the */
- /* encryption. If so, we would be either decrypting unencrypted text */
- /* or not decrypting encrypted text. So we must move this call to */
- /* all functions that call ttxin(). In OS2 that means os2_netxin() */
- /* where the Telnet Negotiations are handled. */
- if (u_encrypt)
- ck_tn_decrypt(buf,len);
- #endif /* CK_ENCRYPTION */
- #endif /* COMMENT */
- return(len);
- }
- /* N E T I N C -- Input character from network */
- #ifdef NETLEBUF
- #define LEBUF
- #endif /* NETLEBUF */
- #ifdef TTLEBUF
- #define LEBUF
- #endif /* TTLEBUF */
- #ifndef LEBUF
- #ifdef OS2
- #define LEBUF
- #endif /* OS2 */
- #endif /* LEBUF */
- int
- netinc(timo) int timo; {
- #ifdef TCPIPLIB
- int x; unsigned char c; /* The locals. */
- #ifdef NETLEBUF
- if (ttpush >= 0) {
- debug(F111,"netinc","ttpush",ttpush);
- c = ttpush;
- ttpush = -1;
- return(c);
- }
- if (le_data) {
- if (le_getchar((CHAR *)&c) > 0) {
- debug(F111,"netinc le_getchar","c",c);
- return(c);
- }
- }
- #endif /* NETLEBUF */
- if (ttyfd == -1) {
- debug(F100,"netinc socket is closed","",0);
- return(-2);
- }
- #ifdef CK_KERBEROS
- #ifdef KRB4
- #ifdef RLOGCODE
- if (ttnproto == NP_EK4LOGIN) {
- if ((x = krb4_des_read(ttyfd,&c,1)) == 0)
- return(-1);
- else if (x < 0)
- return(-2);
- else
- return(c);
- }
- #endif /* RLOGCODE */
- #endif /* KRB4 */
- #ifdef KRB5
- #ifdef RLOGCODE
- if (ttnproto == NP_EK5LOGIN) {
- if ((x = krb5_des_read(ttyfd,&c,1,0)) == 0)
- return(-1);
- else if (x < 0)
- return(-2);
- else
- return(c);
- }
- #endif /* RLOGCODE */
- #ifdef KRB5_U2U
- if (ttnproto == NP_K5U2U) {
- if ((x = krb5_u2u_read(ttyfd,&c,1)) == 0)
- return(-1);
- else if (x < 0)
- return(-2);
- else
- return(c);
- }
- #endif /* KRB5_U2U */
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- #ifdef OS2
- RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
- #endif /* OS2 */
- if (ttibn > 0) { /* Something in internal buffer? */
- #ifdef COMMENT
- debug(F100,"netinc char in buf","",0); /* Yes. */
- #endif /* COMMENT */
- x = 0; /* Success. */
- } else { /* Else must read from network. */
- x = -1; /* Assume failure. */
- #ifdef DEBUG
- debug(F101,"netinc goes to net, timo","",timo);
- #endif /* DEBUG */
- #ifdef CK_SSL
- /*
- * In the case of OpenSSL, it is possible that there is still
- * data waiting in the SSL session buffers that has not yet
- * been read by Kermit. If this is the case we must process
- * it without calling select() because select() will not return
- * with an indication that there is data to be read from the
- * socket. If there is no data pending in the SSL session
- * buffers then fall through to the select() code and wait for
- * some data to arrive.
- */
- if (ssl_active_flag) {
- x = SSL_pending(ssl_con);
- if (x < 0) {
- debug(F111,"netinc","SSL_pending error",x);
- netclos();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- } else if ( x > 0 ) {
- if ( ttbufr() >= 0 ) {
- x = netinc(timo);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(x);
- }
- }
- x = -1;
- } else if (tls_active_flag) {
- x = SSL_pending(tls_con);
- if (x < 0) {
- debug(F111,"netinc","TLS_pending error",x);
- netclos();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- } else if ( x > 0 ) {
- if ( ttbufr() >= 0 ) {
- x = netinc(timo);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(x);
- }
- }
- x = -1;
- }
- #endif /* CK_SSL */
- #ifndef LEBUF
- if (timo == 0) { /* Untimed case. */
- while (1) { /* Wait forever if necessary. */
- if (ttbufr() < 0) /* Refill buffer. */
- break; /* Error, fail. */
- if (ttibn > 0) { /* Success. */
- x = 0;
- break;
- }
- }
- } else /* Timed case... */
- #endif /* LEBUF */
- {
- #ifdef NT_TCP_OVERLAPPED
- /* This code is for use on NT when we are using */
- /* Overlapped I/O to handle reads. In the case */
- /* of outstanding reads select() doesn't work */
- if (WaitForOverlappedReadData(timo)) {
- while (1) {
- if (ttbufr() < 0) /* Keep trying to refill it. */
- break; /* Till we get an error. */
- if (ttibn > 0) { /* Or we get a character. */
- x = 0;
- break;
- }
- }
- }
- #else /* NT_TCP_OVERLAPPED */
- #ifdef BSDSELECT
- fd_set rfds;
- struct timeval tv;
- int timeout = timo < 0 ? -timo : 1000 * timo;
- debug(F101,"netinc BSDSELECT","",timo);
- for ( ; timeout >= 0; timeout -= (timo ? 100 : 0)) {
- int rc;
- debug(F111,"netinc","timeout",timeout);
- /* Don't move select() initialization out of the loop. */
- FD_ZERO(&rfds);
- FD_SET(ttyfd, &rfds);
- tv.tv_sec = tv.tv_usec = 0L;
- if (timo)
- tv.tv_usec = (long) 100000L;
- else
- tv.tv_sec = 30;
- #ifdef NT
- WSASafeToCancel = 1;
- #endif /* NT */
- rc = select(FD_SETSIZE,
- #ifdef __DECC
- #ifdef INTSELECT
- (int *)
- #else /* def INTSELECT */
- (fd_set *)
- #endif /* def INTSELECT [else] */
- #else /* def __DECC */
- (fd_set *)
- #endif /* def __DECC [else] */
- &rfds, NULL, NULL, &tv);
- if (rc < 0) {
- int s_errno = socket_errno;
- debug(F111,"netinc","select",rc);
- debug(F111,"netinc","socket_errno",s_errno);
- if (s_errno) {
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- }
- }
- debug(F111,"netinc","select",rc);
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- if (!FD_ISSET(ttyfd, &rfds)) {
- #ifdef LEBUF
- if (le_inbuf() > 0) {
- timeout = -1;
- break;
- }
- #endif /* LEBUF */
- /* If waiting forever we have no way of knowing if the */
- /* socket closed so try writing a 0-length TCP packet */
- /* which should force an error if the socket is closed */
- if (!timo) {
- if ((rc = socket_write(ttyfd,"",0)) < 0) {
- int s_errno = socket_errno;
- debug(F101,"netinc socket_write error","",s_errno);
- #ifdef OS2
- if (os2socketerror(s_errno) < 0) {
- ReleaseTCPIPMutex();
- return(-2);
- }
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1); /* Call it an i/o error */
- }
- }
- continue;
- }
- while (1) {
- if (ttbufr() < 0) { /* Keep trying to refill it. */
- timeout = -1;
- break; /* Till we get an error. */
- }
- if (ttibn > 0) { /* Or we get a character. */
- x = 0;
- timeout = -1;
- break;
- }
- }
- }
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- #else /* !BSDSELECT */
- #ifdef IBMSELECT
- /*
- Was used by OS/2, currently not used, but might come in handy some day...
- ... and it came in handy! For our TCP/IP layer, it avoids all the fd_set
- and timeval stuff since this is the only place where it is used.
- */
- int socket = ttyfd;
- int timeout = timo < 0 ? -timo : 1000 * timo;
- debug(F101,"netinc IBMSELECT","",timo);
- for ( ; timeout >= 0; timeout -= (timo ? 100 : 0)) {
- if (select(&socket, 1, 0, 0, 100L) == 1) {
- while (1) {
- if (ttbufr() < 0) { /* Keep trying to refill it. */
- timeout = -1;
- break; /* Till we get an error. */
- }
- if (ttibn > 0) { /* Or we get a character. */
- x = 0;
- timeout = -1;
- break;
- }
- }
- }
- #ifdef LEBUF
- else if (le_inbuf() > 0) {
- timeout = -1;
- break;
- }
- #endif /* LEBUF */
- }
- #else /* !IBMSELECT */
- #ifdef WINSOCK
- /* Actually, under WinSock we have a better mechanism than select() */
- /* for setting timeouts (SO_RCVTIMEO, SO_SNDTIMEO) */
- SOCKET socket = ttyfd;
- debug(F101,"netinc NTSELECT","",timo);
- if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timo,
- sizeof(timo)) == NO_ERROR)
- while (1) {
- if (ttbufr() < 0) /* Keep trying to refill it. */
- break; /* Till we get an error. */
- if (ttibn > 0) { /* Or we get a character. */
- x = 0;
- break;
- }
- }
- #else /* WINSOCK */
- /*
- If we can't use select(), then we use the regular alarm()/signal()
- timeout mechanism.
- */
- debug(F101,"netinc alarm","",timo);
- x = alrm_execute(ckjaddr(njbuf),timo,nettout,donetinc,failnetinc);
- ttimoff(); /* Timer off. */
- #endif /* WINSOCK */
- #endif /* IBMSELECT */
- #endif /* BSDSELECT */
- #endif /* NT_TCP_OVERLAPPED */
- }
- }
- #ifdef LEBUF
- if (le_inbuf() > 0) { /* If data was inserted into the */
- if (le_getchar((CHAR *)&c) > 0) {/* Local Echo buffer while the */
- #ifdef OS2 /* was taking place do not mix */
- ReleaseTCPIPMutex(); /* the le data with the net data */
- #endif /* OS2 */
- return(c);
- }
- }
- #endif /* LEBUF */
- if (x < 0) { /* Return -1 if we failed. */
- debug(F100,"netinc timed out","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- } else { /* Otherwise */
- c = ttibuf[ttibp]; /* Return the first char in ttibuf[] */
- if (deblog) {
- #ifndef COMMENT
- debug(F101,"netinc returning","",c);
- #endif /* COMMENT */
- if (c == 0) {
- debug(F101,"netinc 0 ttibn","",ttibn);
- debug(F101,"netinc 0 ttibp","",ttibp);
- #ifdef BETADEBUG
- {
- #ifdef OS2
- extern int tt_type_mode;
- if ( !ISVTNT(tt_type_mode) )
- #endif /* OS2 */
- ckhexdump("netinc &ttbuf[ttibp]",&ttibuf[ttibp],ttibn);
- }
- #endif /* BETADEBUG */
- }
- }
- ttibp++;
- ttibn--;
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- #ifdef CK_ENCRYPTION
- if (TELOPT_U(TELOPT_ENCRYPTION))
- ck_tn_decrypt(&c,1);
- #endif /* CK_ENCRYPTION */
- return(c);
- }
- #else /* Not using TCPIPLIB */
- return(-1);
- #endif /* TCPIPLIB */
- }
- /* N E T T O L -- Output a string of bytes to the network */
- /*
- Call with s = pointer to string, n = length.
- Returns number of bytes actually written on success, or
- -1 on i/o error, -2 if called improperly.
- */
- int
- nettol(s,n) CHAR *s; int n; {
- #ifdef TCPIPLIB
- int count = 0;
- int len = n;
- int try = 0;
- if (ttyfd == -1) {
- debug(F100,"nettol socket is closed","",0);
- return -1;
- }
- debug(F101,"nettol TCPIPLIB ttnet","",ttnet);
- #ifdef COMMENT
- ckhexdump("nettol",s,n);
- #endif /* COMMENT */
- #ifdef CK_KERBEROS
- #ifdef KRB4
- #ifdef RLOGCODE
- if (ttnproto == NP_EK4LOGIN) {
- return(krb4_des_write(ttyfd,s,n));
- }
- #endif /* RLOGCODE */
- #endif /* KRB4 */
- #ifdef KRB5
- #ifdef RLOGCODE
- if (ttnproto == NP_EK5LOGIN) {
- return(krb5_des_write(ttyfd,s,n,0));
- }
- #endif /* RLOGCODE */
- #ifdef KRB5_U2U
- if (ttnproto == NP_K5U2U) {
- return(krb5_u2u_write(ttyfd,s,n));
- }
- #endif /* KRB5_U2U */
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- #ifdef CK_ENCRYPTION
- if (TELOPT_ME(TELOPT_ENCRYPTION))
- ck_tn_encrypt(s,n);
- #endif /* CK_ENCRYPTION */
- #ifdef CK_SSL
- if (ssl_active_flag || tls_active_flag) {
- int error, r;
- /* Write using SSL */
- ssl_retry:
- if (ssl_active_flag)
- r = SSL_write(ssl_con, s, len /* >1024?1024:len */);
- else
- r = SSL_write(tls_con, s, len /* >1024?1024:len */);
- switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,r)) {
- case SSL_ERROR_NONE:
- debug(F111,"nettol","SSL_write",r);
- if ( r == len )
- return(n);
- s += r;
- len -= r;
- goto ssl_retry;
- case SSL_ERROR_WANT_WRITE:
- debug(F100,"nettol SSL_ERROR_WANT_WRITE","",0);
- return(-1);
- case SSL_ERROR_WANT_READ:
- debug(F100,"nettol SSL_ERROR_WANT_READ","",0);
- return(-1);
- case SSL_ERROR_SYSCALL:
- if ( r == 0 ) { /* EOF */
- netclos();
- return(-2);
- } else {
- int rc = -1;
- #ifdef NT
- int gle = GetLastError();
- debug(F111,"nettol SSL_ERROR_SYSCALL",
- "GetLastError()",gle);
- rc = os2socketerror(gle);
- if (rc == -1)
- rc = -2;
- else if ( rc == -2 )
- rc = -1;
- #endif /* NT */
- return(rc);
- }
- case SSL_ERROR_WANT_X509_LOOKUP:
- debug(F100,"nettol SSL_ERROR_WANT_X509_LOOKUP","",0);
- netclos();
- return(-2);
- case SSL_ERROR_SSL:
- debug(F100,"nettol SSL_ERROR_SSL","",0);
- if (bio_err!=NULL) {
- int len;
- extern char ssl_err[];
- BIO_printf(bio_err,"nettol() SSL_ERROR_SSL\n");
- ERR_print_errors(bio_err);
- len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
- ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
- debug(F110,"nettol SSL_ERROR_SSL",ssl_err,0);
- if (ssl_debug_flag)
- printf(ssl_err);
- } else if (ssl_debug_flag) {
- debug(F100,"nettol SSL_ERROR_SSL","",0);
- fflush(stderr);
- fprintf(stderr,"nettol() SSL_ERROR_SSL\n");
- ERR_print_errors_fp(stderr);
- }
- #ifdef COMMENT
- netclos();
- return(-2);
- #else
- return(-1);
- #endif
- case SSL_ERROR_ZERO_RETURN:
- debug(F100,"nettol SSL_ERROR_ZERO_RETURN","",0);
- netclos();
- return(-2);
- default:
- debug(F100,"nettol SSL_ERROR_?????","",0);
- netclos();
- return(-2);
- }
- }
- #endif /* CK_SSL */
- nettol_retry:
- try++; /* Increase the try counter */
- if (ttnet == NET_TCPB) {
- #ifdef BSDSELECT
- fd_set wfds;
- struct timeval tv;
- debug(F101,"nettol BSDSELECT","",0);
- tv.tv_usec = 0L;
- tv.tv_sec=30;
- #ifdef NT
- WSASafeToCancel = 1;
- #endif /* NT */
- #ifdef STREAMING
- do_select:
- #endif /* STREAMING */
- FD_ZERO(&wfds);
- FD_SET(ttyfd, &wfds);
- if (select(FD_SETSIZE, NULL,
- #ifdef __DECC
- #ifndef __DECC_VER
- (int *)
- #endif /* __DECC_VER */
- #endif /* __DECC */
- &wfds, NULL, &tv) < 0) {
- int s_errno = socket_errno;
- debug(F101,"nettol select failed","",s_errno);
- #ifdef BETADEBUG
- printf("nettol select failed: %d\n", s_errno);
- #endif /* BETADEBUG */
- #ifdef NT
- WSASafeToCancel = 0;
- if (!win95selectbug)
- #endif /* NT */
- return(-1);
- }
- if (!FD_ISSET(ttyfd, &wfds)) {
- #ifdef STREAMING
- if (streaming)
- goto do_select;
- #endif /* STREAMING */
- debug(F111,"nettol","!FD_ISSET",ttyfd);
- #ifdef NT
- WSASafeToCancel = 0;
- if (!win95selectbug)
- #endif /* NT */
- return(-1);
- }
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- #else /* BSDSELECT */
- #ifdef IBMSELECT
- {
- int tries = 0;
- debug(F101,"nettol IBMSELECT","",0);
- while (select(&ttyfd, 0, 1, 0, 1000) != 1) {
- int count;
- if (tries++ >= 60) {
- /* if after 60 seconds we can't get permission to write */
- debug(F101,"nettol select failed","",socket_errno);
- return(-1);
- }
- if ((count = nettchk()) < 0) {
- debug(F111,"nettol","nettchk()",count);
- return(count);
- }
- }
- }
- #endif /* IBMSELECT */
- #endif /* BSDSELECT */
- if ((count = socket_write(ttyfd,s,n)) < 0) {
- int s_errno = socket_errno; /* maybe a function */
- debug(F101,"nettol socket_write error","",s_errno);
- #ifdef OS2
- if (os2socketerror(s_errno) < 0)
- return(-2);
- #endif /* OS2 */
- return(-1); /* Call it an i/o error */
- }
- if (count < n) {
- debug(F111,"nettol socket_write",s,count);
- if (try > 25) {
- /* don't try more than 25 times */
- debug(F100,"nettol tried more than 25 times","",0);
- return(-1);
- }
- if (count > 0) {
- s += count;
- n -= count;
- }
- debug(F111,"nettol retry",s,n);
- goto nettol_retry;
- } else {
- debug(F111,"nettol socket_write",s,count);
- return(len); /* success - return total length */
- }
- } else
- return(-2);
- #else
- debug(F100,"nettol TCPIPLIB not defined","",0);
- return(-2);
- #endif /* TCPIPLIB */
- }
- /* N E T T O C -- Output character to network */
- /*
- Call with character to be transmitted.
- Returns 0 if transmission was successful, or
- -1 upon i/o error, or -2 if called improperly.
- */
- int
- #ifdef CK_ANSIC
- nettoc(CHAR c)
- #else
- nettoc(c) CHAR c;
- #endif /* CK_ANSIC */
- /* nettoc */ {
- #ifdef UNIX
- return(ttoc(c));
- #else
- #ifdef TCPIPLIB
- unsigned char cc;
- if (ttyfd == -1) {
- debug(F100,"nettoc socket is closed","",0);
- return -1;
- }
- cc = c;
- debug(F101,"nettoc cc","",cc);
- #ifdef CK_KERBEROS
- #ifdef KRB4
- #ifdef RLOGCODE
- if (ttnproto == NP_EK4LOGIN) {
- return(krb4_des_write(ttyfd,&cc,1)==1?0:-1);
- }
- #endif /* RLOGCODE */
- #endif /* KRB4 */
- #ifdef KRB5
- #ifdef RLOGCODE
- if (ttnproto == NP_EK5LOGIN) {
- return(krb5_des_write(ttyfd,&cc,1,0)==1?0:-1);
- }
- #endif /* RLOGCODE */
- #ifdef KRB5_U2U
- if (ttnproto == NP_K5U2U) {
- return(krb5_u2u_write(ttyfd,&cc,1)==1?0:-1);
- }
- #endif /* KRB5_U2U */
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- #ifdef CK_ENCRYPTION
- if ( TELOPT_ME(TELOPT_ENCRYPTION) )
- ck_tn_encrypt(&cc,1);
- #endif /* CK_ENCRYPTION */
- #ifdef CK_SSL
- if (ssl_active_flag || tls_active_flag) {
- int len, error;
- /* Write using SSL */
- ssl_retry:
- if (ssl_active_flag)
- len = SSL_write(ssl_con, &cc, 1);
- else
- len = SSL_write(tls_con, &cc, 1);
- switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,len)) {
- case SSL_ERROR_NONE:
- debug(F111,"nettoc","SSL_write",len);
- return(len == 1 ? 0 : -1);
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_READ:
- return(-1);
- case SSL_ERROR_SYSCALL:
- if ( len == 0 ) { /* EOF */
- netclos();
- return(-2);
- } else {
- int rc = -1;
- #ifdef NT
- int gle = GetLastError();
- debug(F111,"nettoc SSL_ERROR_SYSCALL",
- "GetLastError()",gle);
- rc = os2socketerror(gle);
- if (rc == -1)
- rc = -2;
- else if ( rc == -2 )
- rc = -1;
- #endif /* NT */
- return(rc);
- }
- case SSL_ERROR_SSL:
- if (bio_err!=NULL) {
- int len;
- extern char ssl_err[];
- BIO_printf(bio_err,"nettoc() SSL_ERROR_SSL\n");
- ERR_print_errors(bio_err);
- len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
- ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
- debug(F110,"nettoc SSL_ERROR_SSL",ssl_err,0);
- if (ssl_debug_flag)
- printf(ssl_err);
- } else if (ssl_debug_flag) {
- debug(F100,"nettoc SSL_ERROR_SSL","",0);
- fflush(stderr);
- fprintf(stderr,"nettoc() SSL_ERROR_SSL\n");
- ERR_print_errors_fp(stderr);
- }
- return(-1);
- break;
- case SSL_ERROR_WANT_X509_LOOKUP:
- case SSL_ERROR_ZERO_RETURN:
- default:
- netclos();
- return(-2);
- }
- }
- #endif /* CK_SSL */
- if (ttnet == NET_TCPB) {
- #ifdef BSDSELECT
- fd_set wfds;
- struct timeval tv;
- debug(F101,"nettoc BSDSELECT","",0);
- tv.tv_usec = 0L;
- tv.tv_sec = 30;
- #ifdef STREAMING
- do_select:
- #endif /* STREAMING */
- FD_ZERO(&wfds);
- FD_SET(ttyfd, &wfds);
- if (select(FD_SETSIZE, NULL,
- #ifdef __DECC
- #ifndef __DECC_VER
- (int *)
- #endif /* __DECC_VER */
- #endif /* __DECC */
- &wfds, NULL, &tv) < 0) {
- int s_errno = socket_errno;
- debug(F101,"nettoc select failed","",s_errno);
- #ifdef BETADEBUG
- printf("nettoc select failed: %d\n", s_errno);
- #endif /* BETADEBUG */
- #ifdef NT
- WSASafeToCancel = 0;
- if (!win95selectbug)
- #endif /* NT */
- return(-1);
- }
- if (!FD_ISSET(ttyfd, &wfds)) {
- #ifdef STREAMING
- if (streaming)
- goto do_select;
- #endif /* STREAMING */
- debug(F111,"nettoc","!FD_ISSET",ttyfd);
- #ifdef NT
- WSASafeToCancel = 0;
- if (!win95selectbug)
- #endif /* NT */
- return(-1);
- }
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- #else /* BSDSELECT */
- #ifdef IBMSELECT
- {
- int tries = 0;
- while (select(&ttyfd, 0, 1, 0, 1000) != 1) {
- int count;
- if (tries++ >= 60) {
- /* if after 60 seconds we can't get permission to write */
- debug(F101,"nettoc select failed","",socket_errno);
- return(-1);
- }
- if ((count = nettchk()) < 0) {
- debug(F111,"nettoc","nettchk()",count);
- return(count);
- }
- }
- }
- #endif /* IBMSELECT */
- #endif /* BSDSELECT */
- if (socket_write(ttyfd,&cc,1) < 1) {
- int s_errno = socket_errno; /* maybe a function */
- debug(F101,"nettoc socket_write error","",s_errno);
- #ifdef OS2
- if (os2socketerror(s_errno) < 0)
- return(-2);
- #endif /* OS2 */
- return(-1);
- }
- debug(F101,"nettoc socket_write","", cc);
- return(0);
- } else return(-2);
- #else
- return(-2);
- #endif /* TCPIPLIB */
- #endif /* UNIX */
- }
- /* N E T F L U I -- Flush network input buffer */
- #ifdef TNCODE
- static int
- #ifdef CK_ANSIC
- netgetc(int timo) /* Input function to point to... */
- #else /* CK_ANSIC */
- netgetc(timo) int timo;
- #endif /* CK_ANSIC */
- { /* ...in the tn_doop() call */
- #ifdef TCPIPLIB
- return netinc(timo);
- #else /* TCPIPLIB */
- return ttinc(timo);
- #endif /* TCPIPLIB */
- }
- #endif /* TNCODE */
- int
- netflui() {
- int n;
- int ch;
- #ifdef NETLEBUF
- ttpush = -1; /* Clear the peek-ahead char */
- while (le_data && (le_inbuf() > 0)) {
- CHAR ch = '\0';
- if (le_getchar(&ch) > 0) {
- debug(F101,"ttflui le_inbuf ch","",ch);
- }
- }
- #endif /* NETLEBUF */
- #ifdef TCPIPLIB
- #ifdef OS2
- RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
- #endif /* OS2 */
- #ifdef TNCODE
- if (ttnproto == NP_TELNET) {
- /* Netflui must process Telnet negotiations or get out of sync */
- if ((n = nettchk()) <= 0)
- goto exit_flui;
- while (n-- > 0) {
- ch = netinc(1);
- if (ch == IAC) {
- extern int duplex; /* this really shouldn't be here but ... */
- int tx = tn_doop((CHAR)(ch & 0xff),duplex,netgetc);
- if (tx == 1) duplex = 1;
- else if (tx == 2) duplex = 0;
- n = nettchk();
- }
- }
- } else
- #endif /* TNCODE */
- {
- ttibuf[ttibp+ttibn] = '\0';
- debug(F111,"netflui 1",ttibuf,ttibn);
- #ifdef CK_ENCRYPTION
- if (TELOPT_U(TELOPT_ENCRYPTION)) {
- ck_tn_decrypt(&ttibuf[ttibp],ttibn);
- }
- #endif /* CK_ENCRYPTION */
- ttibn = ttibp = 0; /* Flush internal buffer *FIRST* */
- if (ttyfd < 1)
- goto exit_flui;
- if ((n = nettchk()) > 0) { /* Now see what's waiting on the net */
- if (n > TTIBUFL) n = TTIBUFL; /* and sponge it up */
- debug(F101,"netflui 2","",n); /* ... */
- n = socket_read(ttyfd,ttibuf,n); /* into our buffer */
- if (n >= 0) ttibuf[n] = '\0';
- debug(F111,"netflui 3",ttibuf,n);
- #ifdef CK_ENCRYPTION
- if (TELOPT_U(TELOPT_ENCRYPTION)) {
- ck_tn_decrypt(&ttibuf[ttibp],n);
- }
- #endif /* CK_ENCRYPTION */
- ttibuf[0] = '\0';
- }
- }
- #else /* !TCPIPLIB */
- if (ttyfd < 1)
- goto exit_flui;
- #ifdef TNCODE
- if (ttnproto == NP_TELNET) {
- if ((n = ttchk()) <= 0)
- goto exit_flui;
- while (n-- >= 0) {
- /* Netflui must process Telnet negotiations or get out of sync */
- ch = ttinc(1);
- if (ch == IAC) {
- extern int duplex; /* this really shouldn't be here but ... */
- int tx = tn_doop((CHAR)(ch & 0xff),duplex,netgetc);
- if (tx == 1) duplex = 1;
- else if (tx == 2) duplex = 0;
- n = ttchk();
- }
- };
- } else
- #endif /* TNCODE */
- if ((n = ttchk()) > 0) {
- debug(F101,"netflui non-TCPIPLIB","",n);
- while ((n--) && ttinc(1) > -1) /* Don't worry, ttinc() is buffered */
- ; /* and it handles the decryption... */
- }
- #endif /* TCPIPLIB */
- exit_flui:
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(0);
- }
- #ifdef CK_KERBEROS
- /* The following two functions are required for encrypted rlogin */
- /* They are called with nettoc() or nettol() are transmitting */
- /* encrypted data. They call a function to encrypt the data */
- /* and that function needs to be able to write to/read from the */
- /* network in an unimpeded manner. Hence, these two simple fns. */
- int
- net_write(fd, buf, len)
- int fd;
- register const char *buf;
- int len;
- {
- int cc;
- register int wrlen = len;
- do {
- #ifdef TCPIPLIB
- cc = socket_write(fd, buf, wrlen);
- #else
- cc = write(fd,buf,wrlen);
- #endif /* TCPIPLIB */
- if (cc < 0) {
- int s_errno = socket_errno;
- debug(F101,"net_write error","",s_errno);
- #ifdef OS2
- if (os2socketerror(s_errno) < 0)
- return(-1);
- else
- continue;
- #else /* OS2 */
- if (errno == EINTR)
- continue;
- return(-1);
- #endif /* OS2 */
- }
- else {
- buf += cc;
- wrlen -= cc;
- }
- } while (wrlen > 0);
- return(len);
- }
- int
- net_read(fd, buf, len)
- int fd;
- register char *buf;
- register int len;
- {
- int cc, len2 = 0;
- do {
- #ifdef TCPIPLIB
- cc = socket_read(fd, buf, len);
- #else
- cc = read(fd,buf,len);
- #endif
- if (cc < 0) {
- int s_errno = socket_errno;
- debug(F101,"net_read error","",s_errno);
- #ifdef OS2
- if (os2socketerror(s_errno) < 0)
- return(-1);
- #endif /* OS2 */
- return(cc); /* errno is already set */
- }
- else if (cc == 0) {
- netclos();
- return(len2);
- } else {
- buf += cc;
- len2 += cc;
- len -= cc;
- }
- } while (len > 0);
- return(len2);
- }
- #endif /* CK_KERBEROS */
- #endif /* NONET */
- /* getlocalipaddr() attempts to resolve an IP Address for the local machine.
- * If the host is multi-homed it returns only one address.
- *
- * Two techniques are used.
- * (1) get the local host name and perform a DNS lookup, then take
- * the first entry;
- * (2) open a UDP socket, use it to connect to a fictitious host (it's OK,
- * no data is sent), then retrieve the local address from the socket.
- * Note: the second technique won't work on Microsoft systems. See
- * Article ID: Q129065 PRB: Getsockname() Returns IP Address 0.0.0.0 for UDP
- */
- /* Technique number one cannot work reliably if the machine is a laptop
- * and the hostname is associated with a physical adapter which is not
- * installed and a PPP connection is being used instead. This is because
- * the hostname DNS lookup will succeed for the physical adapter even though
- * it would be impossible to use it. In NT4 SP4, the gethostbyname()
- * when given the result of gethostname() returns not the real DNS entries
- * for that name+domain. Instead it returns all of the static and dynamic
- * IP addresses assigned to any physical or virtual adapter defined in the
- * system regardless of whether or not it is installed. The order of the
- * addresses is fixed according to the binding order in the NT registry.
- */
- /*
- * It appears that calling gethostbyname(NULL) is more reliable than
- * calling gethostbyname(gethostname()) on Windows. So on Windows we will
- * only call gethostbyname(NULL).
- */
- int
- getlocalipaddr() {
- #ifndef datageneral
- struct sockaddr_in l_sa;
- struct sockaddr_in r_sa;
- GSOCKNAME_T slen = sizeof(struct sockaddr_in);
- int sock;
- int rc;
- struct in_addr laddr;
- /* if still not resolved, then try second strategy */
- /* This second strategy does not work on Windows */
- debug(F100,"getlocalipaddr","",0);
- memset(&l_sa,0,slen);
- memset(&r_sa,0,slen);
- /* get a UDP socket */
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock != -1) {
- /* connect to arbirary port and address (NOT loopback) */
- r_sa.sin_family = AF_INET;
- r_sa.sin_port = htons(IPPORT_ECHO);
- /* The following is an "illegal conversion" in AOS/VS */
- /* (and who knows where else) */
- #ifdef INADDRX
- inaddrx = inet_addr("128.127.50.1");
- r_sa.sin_addr.s_addr = *(unsigned long *)&inaddrx;
- #else
- r_sa.sin_addr.s_addr = inet_addr("128.127.50.1");
- #endif /* INADDRX */
- rc = connect(sock, (struct sockaddr *) &r_sa, sizeof(struct sockaddr));
- if (!rc) { /* get local address */
- getsockname(sock,(struct sockaddr *)&l_sa,&slen);
- #ifdef TCPIPLIB
- socket_close(sock); /* We're done with the socket */
- #else
- close(sock);
- #endif /* TCPIPLIB */
- if (l_sa.sin_addr.s_addr != INADDR_ANY) {
- myxipaddr = ntohl(l_sa.sin_addr.s_addr);
- ckstrncpy(myipaddr,(char *)inet_ntoa(l_sa.sin_addr),20);
- debug(F110,"getlocalipaddr setting buf to",myipaddr,0);
- return(0);
- }
- }
- }
- return getlocalipaddrs(myipaddr,sizeof(myipaddr),0);
- #else /* datageneral */
- return(-1);
- #endif /* datageneral */
- }
- int
- getlocalipaddrs(buf,bufsz,index)
- char * buf;
- int bufsz;
- int index;
- /* getlocalipaddrs */ {
- #ifndef datageneral
- char localhost[256];
- struct hostent * host=NULL;
- struct sockaddr_in l_sa;
- struct sockaddr_in r_sa;
- GSOCKNAME_T slen = sizeof(struct sockaddr_in);
- int rc;
- #ifdef COMMENT
- int sock;
- char messageBuf[60];
- struct in_addr laddr;
- #endif /* COMMENT */
- debug(F100,"getlocalipaddrs","",0);
- memset(&l_sa,0,slen);
- memset(&r_sa,0,slen);
- /* init local address (to zero) */
- l_sa.sin_addr.s_addr = INADDR_ANY;
- #ifdef CKGHNLHOST
- rc = gethostname(localhost, 256);
- debug(F110,"getlocalipaddrs localhost",localhost,0);
- #else
- /* This doesn't work on some platforms, e.g. Solaris */
- rc = 0;
- localhost[0] = '\0';
- #ifdef NT
- if ( winsock_version < 20 ) {
- rc = gethostname(localhost, 256);
- debug(F110,"getlocalipaddrs localhost",localhost,0);
- }
- #endif /* NT */
- #endif /* CKGHNLHOST */
- if (!rc) {
- /* resolve host name for local address */
- debug(F110,"getlocalipaddrs","calling gethostbyname()",0);
- host = gethostbyname(localhost);
- /* debug(F111,"getlocalipaddrs","gethostbyname() returned",host); */
- if (host) {
- #ifdef HADDRLIST
- host = ck_copyhostent(host);
- if ( index < 0 || index > 63 || !host->h_addr_list[index] ) {
- buf[0] = '\0';
- return(-1);
- }
- l_sa.sin_addr.s_addr =
- *((unsigned long *) (host->h_addr_list[index]));
- ckstrncpy(buf,(char *)inet_ntoa(l_sa.sin_addr),20);
- debug(F110,"getlocalipaddrs setting buf to",buf,0);
- #ifdef COMMENT
- /* This is for reporting multiple IP Address */
- while (host->h_addr_list && host->h_addr_list[0]) {
- l_sa.sin_addr.s_addr =
- *((unsigned long *) (host->h_addr_list[0]));
- ckstrncpy(messageBuf,
- (char *)inet_ntoa(l_sa.sin_addr),60);
- if (tcp_address) {
- if (!strcmp(messageBuf,tcp_address))
- ckstrncpy(myipaddr,tcp_address,20);
- }
- debug(F110,"getlocalipaddrs ip address list", messageBuf, 0);
- host->h_addr_list++;
- }
- #endif /* COMMENT */
- #else /* HADDRLIST */
- if (index != 0) {
- buf[0] = '\0';
- return(-1);
- }
- l_sa.sin_addr.s_addr = *((unsigned long *) (host->h_addr));
- ckstrncpy(buf,(char *)inet_ntoa(l_sa.sin_addr),bufsz);
- debug(F110,"getlocalipaddrs setting buf to",buf,0);
- #endif /* HADDRLIST */
- return(0);
- } else debug(F110,
- "getlocalipaddrs: gethostbyname() failed",
- localhost,
- 0
- );
- }
- #endif /* datageneral */
- return(-1);
- }
- #ifdef RLOGCODE /* TCP/IP RLOGIN protocol support code */
- int
- rlog_naws() {
- struct rlog_naws {
- unsigned char id[4];
- unsigned short rows, cols, ypix, xpix;
- } nawsbuf;
- if (ttnet != NET_TCPB)
- return 0;
- if (ttnproto != NP_RLOGIN
- #ifdef CK_KERBEROS
- && ttnproto != NP_K4LOGIN
- && ttnproto != NP_EK4LOGIN
- && ttnproto != NP_K5LOGIN
- && ttnproto != NP_EK5LOGIN
- #endif /* CK_KERBEROS */
- )
- return 0;
- if (!TELOPT_ME(TELOPT_NAWS))
- return 0;
- debug(F100,"rlogin Window Size sent","",0);
- nawsbuf.id[0] = nawsbuf.id[1] = 0377;
- nawsbuf.id[2] = nawsbuf.id[3] = 's';
- #ifdef OS2
- nawsbuf.rows = htons((unsigned short) (VscrnGetHeight(VTERM)
- -(tt_status[VTERM]?1:0)));
- nawsbuf.cols = htons((unsigned short) VscrnGetWidth(VTERM));
- #else /* OS2 */
- nawsbuf.rows = htons((unsigned short) tt_rows);
- nawsbuf.cols = htons((unsigned short) tt_cols);
- #endif /* OS2 */
- nawsbuf.ypix = htons(0); /* y pixels */
- nawsbuf.xpix = htons(0); /* x pixels */
- if (ttol((CHAR *)(&nawsbuf), sizeof(nawsbuf)) < 0)
- return(-1);
- return(0);
- }
- #ifdef OS2ORUNIX
- #define RLOGOUTBUF
- #endif /* OS2 */
- static int
- #ifdef CK_ANSIC
- rlog_ini(CHAR * hostname, int port,
- struct sockaddr_in * l_addr, struct sockaddr_in * r_addr)
- #else /* CK_ANSIC */
- rlog_ini(hostname, port, l_addr, r_addr)
- CHAR * hostname;
- int port;
- struct sockaddr_in * l_addr;
- struct sockaddr_in * r_addr;
- #endif /* CK_ANSIC */
- /* rlog_ini */ {
- #ifdef RLOGOUTBUF
- char outbuf[512];
- int outbytes=0;
- #endif /* RLOGOUTBUF */
- int flag = 0;
- #define TERMLEN 16
- #define CONSPDLEN 16
- CHAR localuser[UIDBUFLEN+1];
- CHAR remoteuser[UIDBUFLEN+1];
- int userlen = 0;
- CHAR term_speed[TERMLEN+CONSPDLEN+1];
- #ifdef CONGSPD
- long conspd = -1L;
- #endif /* CONGSPD */
- #ifdef OS2
- extern int tt_type, max_tt;
- extern struct tt_info_rec tt_info[];
- #endif /* OS2 */
- int i, n;
- int rc = 0;
- tn_reset(); /* This call will reset all of the Telnet */
- /* options and then quit. We need to do */
- /* this since we use the Telnet options */
- /* to hold various state information */
- duplex = 0; /* Rlogin is always remote echo */
- rlog_inband = 0;
- #ifdef CK_TTGWSIZ
- /*
- But compute the values anyway before the first read since the out-
- of-band NAWS request would arrive before the first data byte (NULL).
- */
- #ifdef OS2
- /* Console terminal screen rows and columns */
- debug(F101,"rlog_ini tt_rows 1","",VscrnGetHeight(VTERM)
- -(tt_status[VTERM]?1:0));
- debug(F101,"rlog_ini tt_cols 1","",VscrnGetWidth(VTERM));
- /* Not known yet */
- if (VscrnGetWidth(VTERM) < 0 ||
- VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) < 0) {
- ttgwsiz(); /* Try to get screen dimensions */
- }
- debug(F101,
- "rlog_ini tt_rows 2",
- "",
- VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
- );
- debug(F101,"rlog_ini tt_cols 2","",VscrnGetWidth(VTERM));
- #else /* OS2 */
- debug(F101,"rlog_ini tt_rows 1","",tt_rows);
- debug(F101,"rlog_ini tt_cols 1","",tt_cols);
- if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
- ttgwsiz(); /* Try to find out */
- }
- debug(F101,"rlog_ini tt_rows 2","",tt_rows);
- debug(F101,"rlog_ini tt_cols 2","",tt_cols);
- #endif /* OS2 */
- #endif /* CK_TTGWSIZ */
- ttflui(); /* Start by flushing the buffers */
- rlog_mode = RL_COOKED;
- /* Determine the user's local username ... */
- localuser[0] = '\0';
- #ifdef NT
- {
- char localuid[UIDBUFLEN+1];
- ckstrncpy((char *)localuser,(char *)GetLocalUser(),UIDBUFLEN);
- }
- if ( !localuser[0] )
- #endif /* NT */
- {
- char * user = getenv("USER");
- if (!user)
- user = "";
- userlen = strlen(user);
- debug(F111,"rlogin getenv(USER)",user,userlen);
- ckstrncpy((char *)localuser,user,UIDBUFLEN);
- debug(F110,"rlog_ini localuser 1",localuser,0);
- }
- if ( !localuser[0] )
- strcpy((char *)localuser,"unknown");
- else if (ck_lcname) {
- cklower((char *)localuser);
- debug(F110,"rlog_ini localuser 2",localuser,0);
- }
- /* And the username to login with */
- if (uidbuf[0]) {
- ckstrncpy((char *)remoteuser,uidbuf,UIDBUFLEN);
- debug(F110,"rlog_ini remoteuser 1",remoteuser,0);
- } else if (localuser[0]) {
- ckstrncpy((char *)remoteuser,(char *)localuser,UIDBUFLEN);
- debug(F110,"rlog_ini remoteuser 2",remoteuser,0);
- } else {
- remoteuser[0] = '\0';
- debug(F110,"rlog_ini remoteuser 3",remoteuser,0);
- }
- if (ck_lcname)
- cklower((char *)remoteuser);
- debug(F110,"rlog_ini remoteuser 4",remoteuser,0);
- /* The command to issue is the terminal type and speed */
- term_speed[0] = '\0';
- if (tn_term) { /* SET TELNET TERMINAL-TYPE value */
- if (*tn_term) { /* (if any) takes precedence. */
- ckstrncpy((char *)term_speed, tn_term, TERMLEN);
- flag = 1;
- }
- } else { /* Otherwise the local terminal type */
- #ifdef OS2
- /* In terminal-emulating versions, it's the SET TERM TYPE value */
- ckstrncpy(term_speed, (tt_type >= 0 && tt_type <= max_tt) ?
- tt_info[tt_type].x_name : "network", TERMLEN);
- #else
- /* In the others, we just look at the TERM environment variable */
- {
- char *p = getenv("TERM");
- if (p)
- ckstrncpy((char *)term_speed,p,TERMLEN);
- else
- term_speed[0] = '\0';
- #ifdef VMS
- for (p = (char *) term_speed; *p; p++) {
- if (*p == '-' && (!strcmp(p,"-80") || !strcmp(p,"-132")))
- break;
- else if (isupper(*p))
- *p = tolower(*p);
- }
- *p = '\0';
- #endif /* VMS */
- }
- #endif /* OS2 */
- }
- n = strlen((char *)term_speed);
- if (n > 0) { /* We have a terminal type */
- if (!flag) { /* If not user-specified */
- for (i = 0; i < n; i++) /* then lowercase it. */
- if (isupper(term_speed[i]))
- term_speed[i] = tolower(term_speed[i]);
- }
- debug(F110,"rlog_ini term_speed 1",term_speed,0);
- #ifdef CONGSPD
- /* conspd() is not yet defined in all ck*tio.c modules */
- conspd = congspd();
- if (conspd > 0L) {
- ckstrncat((char *)term_speed,"/",sizeof(term_speed));
- ckstrncat((char *)term_speed,ckltoa(conspd),sizeof(term_speed));
- } else
- #endif /* CONGSPD */
- ckstrncat((char *)term_speed,"/19200",sizeof(term_speed));
- debug(F110,"rlog_ini term_speed 2",term_speed,0);
- } else {
- term_speed[0] = '\0';
- debug(F110,"rlog_ini term_speed 3",term_speed,0);
- }
- #ifdef CK_KERBEROS
- if (ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN ||
- ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN) {
- int kver, encrypt, rc;
- switch (ttnproto) {
- case NP_K4LOGIN:
- kver = 4;
- encrypt = 0;
- break;
- case NP_EK4LOGIN:
- kver = 4;
- encrypt = 1;
- break;
- case NP_K5LOGIN:
- kver = 5;
- encrypt = 0;
- break;
- case NP_EK5LOGIN:
- kver = 5;
- encrypt = 1;
- break;
- default:
- kver = 0;
- encrypt = 0;
- }
- rc = ck_krb_rlogin(hostname, port,
- localuser, remoteuser, term_speed,
- l_addr, r_addr, kver, encrypt);
- if (!rc) { /* success */
- TELOPT_ME(TELOPT_NAWS) = 1;
- rc = rlog_naws();
- }
- return(rc);
- } else
- #endif /* CK_KERBEROS */
- if (ttnproto == NP_RLOGIN) {
- #ifdef RLOGOUTBUF
- /*
- * The rcmds start the connection with a series of init data:
- *
- * a port number upon which client is listening for stderr data
- * the user's name on the client machine
- * the user's name on the server machine
- * the terminal_type/speed or command to execute
- */
- outbuf[outbytes++] = 0;
- strcpy((char *)outbuf+outbytes,(char *)localuser);
- outbytes += strlen((char *)localuser) + 1;
- strcpy((char *)outbuf+outbytes,(char *)remoteuser);
- outbytes += strlen((char *)remoteuser) + 1;
- strcpy((char *)outbuf+outbytes,(char *)term_speed);
- outbytes += strlen((char *)term_speed) + 1;
- rc = ttol((CHAR *)outbuf,outbytes);
- #else /* RLOGOUTBUF */
- ttoc(0); /* Send an initial NUL as wake-up */
- /* Send each variable with the trailing NUL */
- rc = ttol(localuser,strlen((char *)localuser)+1);
- if (rc > 0)
- rc = ttol(remoteuser,strlen((char *)remoteuser)+1);
- if (rc > 0)
- rc = ttol(term_speed,strlen((char *)term_speed)+1);
- #endif /* RLOGOUTBUF */
- /* Now we are supposed to get back a single NUL as confirmation */
- errno = 0;
- rc = ttinc(60);
- debug(F101,"rlogin first ttinc","",rc);
- if (rc > 0) {
- debug(F101,"rlogin ttinc 1","",rc);
- printf(
- "Rlogin protocol error - 0x%x received instead of 0x00\n", rc);
- return(-1);
- } else if (rc < 0) {
- debug(F101,"rlogin ttinc errno","",errno);
- /* printf("Network error: %d\n", errno); */
- return(-1);
- }
- }
- return(0);
- }
- /* two control messages are defined:
- a double flag byte of 'o' indicates a one-byte message which is
- identical to what was once carried out of band.
- a double flag byte of 'q' indicates a zero-byte message. This
- message is interpreted as two \377 data bytes. This is just a
- quote rule so that binary data from the server does not confuse the
- client. */
- int
- rlog_ctrl(cp, n)
- unsigned char *cp;
- int n;
- {
- if ((n >= 5) && (cp[2] == 'o') && (cp[3] == 'o')) {
- if (rlog_oob(&cp[4],1))
- return(-5);
- return(5);
- } else if ((n >= 4) && (cp[2] == 'q') && (cp[3] == 'q')) {
- /* this is somewhat of a hack */
- cp[2] = '\377';
- cp[3] = '\377';
- return(2);
- }
- return(0);
- }
- static int
- rlog_oob(oobdata, count) CHAR * oobdata; int count; {
- int i;
- int flush = 0;
- debug(F111,"rlogin out_of_band","count",count);
- for (i = 0; i<count; i++) {
- debug(F101,"rlogin out_of_band","",oobdata[i]);
- if (oobdata[i] & 0x01)
- continue;
- if (oobdata[i] & 0x02) { /* Flush Buffered Data not yet displayed */
- debug(F101,"rlogin Flush Buffered Data command","",oobdata[i]);
- /* Only flush the data if in fact we are in a mode that won't */
- /* get out of sync. Ie, not when we are in protocol mode. */
- switch ( what ) {
- case W_NOTHING:
- case W_CONNECT:
- case W_COMMAND:
- if ( rlog_inband )
- flush = 1;
- else
- ttflui();
- break;
- }
- }
- if (oobdata[i] & 0x10) { /* Switch to RAW mode */
- debug(F101,"rlogin Raw Mode command","",oobdata[i]);
- rlog_mode = RL_RAW;
- }
- if (oobdata[i] & 0x20) { /* Switch to COOKED mode */
- debug(F101,"rlogin Cooked Mode command","",oobdata[i]);
- rlog_mode = RL_COOKED;
- }
- if (oobdata[i] & 0x80)
- { /* Send Window Size Info */
- debug(F101,"rlogin Window Size command","",oobdata[i]);
- /* Remember to send WS Info when Window Size changes */
- if ( !TELOPT_ME(TELOPT_NAWS) ) {
- TELOPT_ME(TELOPT_NAWS) = 1;
- rlog_naws();
- }
- }
- }
- return(flush);
- }
- #ifndef TCPIPLIB
- static SIGTYP
- rlogoobh(sig) int sig; {
- #ifdef SOLARIS
- char /* Or should it be char for all? */
- #else
- CHAR
- #endif /* SOLARIS */
- oobdata;
- /* int count = 0; */ /* (not used) */
- while (recv(ttyfd, &oobdata, 1, MSG_OOB) < 0) {
- /*
- * We need to do some special processing here.
- * Just in case the socket is blocked for input
- *
- */
- switch (errno) {
- case EWOULDBLOCK:
- break;
- default:
- return;
- }
- }
- debug(F101,"rlogin out_of_band","",oobdata);
- if (oobdata == 0x02) { /* Flush Buffered Data not yet displayed */
- debug(F101,"rlogin Flush Buffered Data command","",oobdata);
- netflui();
- }
- if (oobdata & 0x10) { /* Switch to raw mode */
- debug(F101,"rlogin Raw Mode command","",oobdata);
- rlog_mode = RL_RAW;
- }
- if (oobdata & 0x20) { /* Switch to cooked mode */
- debug(F101,"rlogin Cooked Mode command","",oobdata);
- rlog_mode = RL_COOKED;
- }
- if (oobdata & 0x80) { /* Send Window Size Info */
- debug(F101,"rlogin Window Size command","",oobdata);
- /* Remember to send WS Info when Window Size changes */
- if ( !TELOPT_ME(TELOPT_NAWS) ) {
- TELOPT_ME(TELOPT_NAWS) = 1;
- rlog_naws();
- }
- }
- }
- #endif /* TCPIPLIB */
- #endif /* RLOGCODE */
- /* Send network BREAK */
- /*
- Returns -1 on error, 0 if nothing happens, 1 if BREAK sent successfully.
- */
- int
- netbreak() {
- CHAR buf[3];
- if (ttnet == NET_TCPB) {
- if (ttnproto == NP_TELNET) {
- #ifdef TNCODE
- buf[0] = (CHAR) IAC; buf[1] = (CHAR) BREAK; buf[2] = (CHAR) 0;
- if (
- #ifdef OS2
- nettol((char *) buf, 2)
- #else
- ttol(buf, 2)
- #endif /* OS2 */
- < 2)
- return(-1);
- if (tn_deb || debses || deblog) {
- extern char tn_msg[];
- ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET SENT ",TELCMD(BREAK),
- NULL,NULL);
- debug(F101,tn_msg,"",BREAK);
- if (debses || tn_deb) tn_debug(tn_msg);
- }
- return(1);
- #else
- debug(F100,"netbreak no TNCODE","",0);
- return(0);
- #endif /* TNCODE */
- }
- /* Insert other TCP/IP protocols here */
- }
- /* Insert other networks here */
- return(0);
- }
- #endif /* NETCONN */
- #ifdef NETCONN
- #ifdef SUNX25
- /*
- SunLink X.25 support by Marcello Frutig, Catholic University,
- Rio de Janeiro, Brazil, 1990.
- */
- /* PAD X.3, X.28 and X.29 support */
- static CHAR x29err[MAXPADPARMS+3] = { X29_ERROR, INVALID_PAD_PARM, '\0' };
- /* Initialize PAD */
- extern CHAR padparms[];
- VOID
- initpad() {
- padparms[PAD_BREAK_CHARACTER] = 0; /* Break character */
- padparms[PAD_ESCAPE] = 1; /* Escape permitted */
- padparms[PAD_ECHO] = 1; /* Kermit PAD does echo */
- padparms[PAD_DATA_FORWARD_CHAR] = 2; /* forward character CR */
- padparms[PAD_DATA_FORWARD_TIMEOUT] = 0; /* no timeout forward condition */
- padparms[PAD_FLOW_CONTROL_BY_PAD] = 0; /* not used */
- padparms[PAD_SUPPRESSION_OF_SIGNALS] = 1; /* allow PAD service signals */
- padparms[PAD_BREAK_ACTION] = 21; /* brk action: INT pk + brk ind*/
- padparms[PAD_SUPPRESSION_OF_DATA] = 0; /* no supression of user data */
- padparms[PAD_PADDING_AFTER_CR] = 0; /* no padding after CR */
- padparms[PAD_LINE_FOLDING] = 0; /* no line fold */
- padparms[PAD_LINE_SPEED] = 0; /* line speed - don't care */
- padparms[PAD_FLOW_CONTROL_BY_USER] = 0; /* flow cont of PAD - not used */
- padparms[PAD_LF_AFTER_CR] = 0; /* no LF insertion after CR */
- padparms[PAD_PADDING_AFTER_LF] = 0; /* no padding after LF */
- padparms[PAD_EDITING] = 1; /* can edit */
- padparms[PAD_CHAR_DELETE_CHAR] = 8; /* character delete character */
- padparms[PAD_BUFFER_DELETE_CHAR] = 21; /* buffer delete character */
- padparms[PAD_BUFFER_DISPLAY_CHAR] = 18; /* buffer display character */
- }
- /* Set PAD parameters */
- VOID
- setpad(s,n) CHAR *s; int n; {
- int i;
- CHAR *ps = s;
- if (n < 1) {
- initpad();
- } else {
- for (i = 0; i < n; i++) {
- if (*ps > MAXPADPARMS)
- x29err[i+2] = *ps;
- else
- padparms[*ps] = *(ps+1);
- ps += 2;
- }
- }
- }
- /* Read PAD parameters */
- VOID
- readpad(s,n,r) CHAR *s; int n; CHAR *r; {
- int i;
- CHAR *ps = s;
- CHAR *pr = r;
- *pr++ = X29_PARAMETER_INDICATION;
- if (n > 0) {
- for (i = 0; i < n; i++, ps++) {
- if (*ps > MAXPADPARMS) {
- x29err[i+2] = *ps++;
- } else {
- *pr++ = *ps;
- *pr++ = padparms[*ps++];
- }
- }
- } else {
- for (i = 1; i < MAXPADPARMS; i++) {
- *pr++ = i;
- *pr++ = padparms[i];
- }
- }
- }
- int
- qbitpkt(s,n) CHAR *s; int n; {
- CHAR *ps = s;
- int x29cmd = *ps;
- CHAR *psa = s+1;
- CHAR x29resp[(MAXPADPARMS*2)+1];
- switch (x29cmd) {
- case X29_SET_PARMS:
- setpad (ps+1,n/2);
- if ((int)strlen((char *)x29err) > 2) {
- ttol(x29err,(int)strlen((char *)x29err));
- x29err[2] = '\0';
- }
- return (-2);
- case X29_READ_PARMS:
- readpad (ps+1,n/2,x29resp);
- setqbit ();
- ttol(x29resp,(n>1)?(n+1):(2*MAXPADPARMS+1));
- if ((int)strlen((char *)x29err) > 2) {
- ttol(x29err,(int)strlen((char *)x29err));
- x29err[2] = '\0';
- }
- resetqbit();
- break;
- case X29_SET_AND_READ_PARMS:
- setpad (ps+1,n/2);
- readpad (ps+1,n/2,x29resp);
- setqbit();
- ttol(x29resp,(n>1)?(n+1):(2*MAXPADPARMS+1));
- if ((int)strlen((char *)x29err) > 2) {
- ttol (x29err,(int)strlen((char *)x29err));
- x29err [2] = '\0';
- }
- resetqbit();
- return (-2);
- case X29_INVITATION_TO_CLEAR:
- (VOID) x25clear();
- return (-1);
- case X29_INDICATION_OF_BREAK:
- break;
- }
- return (0);
- }
- /* PAD break action processor */
- VOID
- breakact() {
- extern char x25obuf[MAXOX25];
- extern int obufl;
- extern int active;
- extern unsigned char tosend;
- static CHAR indbrk[3] = {
- X29_INDICATION_OF_BREAK,
- PAD_SUPPRESSION_OF_DATA,
- 1
- };
- CHAR intudat, cause, diag;
- if (x25stat() < 0) return; /* Ignore if no virtual call established */
- if (padparms[PAD_BREAK_ACTION] != 0) /* Forward condition */
- if (ttol((CHAR *)x25obuf,obufl) < 0) {
- perror ("\r\nCan't send characters");
- active = 0;
- } else {
- bzero (x25obuf,sizeof(x25obuf));
- obufl = 0;
- tosend = 0;
- };
- switch (padparms[PAD_BREAK_ACTION]) {
- case 0 : break; /* do nothing */
- case 1 : /* send interrupt packet with interrupt user data field = 1 */
- intudat = 1;
- x25intr (intudat);
- break;
- case 2 : /* send reset packet with cause and diag = 0 */
- cause = diag = 0;
- x25reset (cause,diag);
- break;
- case 5 : /* send interrupt packet with interrupt user data field = 0 */
- intudat = 0;
- x25intr (intudat);
- setqbit ();
- /* send indication of break without a parameter field */
- ttoc(X29_INDICATION_OF_BREAK);
- resetqbit ();
- break;
- case 8 : active = 0; /* leave data transfer */
- conol ("\r\n");
- break;
- case 21: /* send interrupt packet with interrupt user data field = 0 */
- intudat = 0;
- x25intr (intudat);
- setpad (indbrk+1,2); /* set pad to discard input */
- setqbit ();
- /* send indication of break with parameter field */
- ttol (indbrk,sizeof(indbrk));
- resetqbit ();
- break;
- }
- }
- /* X.25 support functions */
- X25_CAUSE_DIAG diag;
- /*
- Convert a null-terminated string representing an X.121 address
- to a packed BCD form.
- */
- int
- pkx121(str,bcd) char *str; CHAR *bcd; {
- int i, j;
- u_char c;
- i = j = 0;
- while (str[i]) {
- if (i >= 15 || str [i] < '0' || str [i] > '9')
- return (-1);
- c = str [i] - '0';
- if (i & 1)
- bcd [j++] |= c;
- else
- bcd [j] = c << 4;
- i++;
- }
- return (i);
- }
- /* Reads and prints X.25 diagnostic */
- int
- x25diag () {
- int i;
- bzero ((char *)&diag,sizeof(diag));
- if (ioctl(ttyfd,X25_RD_CAUSE_DIAG,&diag)) {
- perror ("Reading X.25 diagnostic");
- return(-1);
- }
- if (diag.datalen > 0) {
- printf ("X.25 Diagnostic :");
- for (i = 0; i < (int)diag.datalen; i++)
- printf(" %02h",diag.data[i])+
- printf ("\r\n");
- }
- return(0);
- }
- /* X.25 Out-of-Band Signal Handler */
- SIGTYP
- x25oobh(foo) int foo; {
- int oobtype;
- u_char oobdata;
- int t;
- (VOID) signal(SIGURG,x25oobh);
- do {
- if (ioctl(ttyfd,X25_OOB_TYPE,&oobtype)) {
- perror ("Getting signal type");
- return;
- }
- switch (oobtype) {
- case INT_DATA:
- if (recv(ttyfd,(char *)&oobdata,1,MSG_OOB) < 0) {
- perror ("Receiving X.25 interrupt data");
- return;
- }
- t = oobdata;
- printf ("\r\nInterrupt received, data = %d\r\n", t);
- break;
- case VC_RESET:
- printf ("\r\nVirtual circuit reset\r\n");
- x25diag ();
- break;
- case N_RESETS:
- printf ("\r\nReset timeout\r\n");
- break;
- case N_CLEARS:
- printf ("\r\nClear timeout\r\n");
- break;
- case MSG_TOO_LONG:
- printf ("\r\nMessage discarded, too long\r\n");
- break;
- default:
- if (oobtype) printf("\r\nUnknown oob type %d\r\n",oobtype);
- break;
- }
- } while (oobtype);
- }
- /* Send a X.25 interrupt packet */
- int
- #ifdef CK_ANSIC
- x25intr(char intr)
- #else
- x25intr(intr) char intr;
- #endif /* CK_ANSIC */
- /* x25intr */ {
- if (send(ttyfd,&intr,1,MSG_OOB) < 0) return(-1);
- debug(F100,"X.25 intr","",0);
- return(0);
- }
- /* Reset X.25 virtual circuit */
- int
- #ifdef CK_ANSIC
- x25reset(char cause, char diagn)
- #else
- x25reset(cause, diagn) char cause; char diagn;
- #endif /* CK_ANSIC */
- /* x25reset */ {
- bzero ((char *)&diag,sizeof(diag));
- diag.flags = 0;
- diag.datalen = 2;
- diag.data[0] = cause;
- diag.data[1] = diagn;
- if (ioctl(ttyfd,X25_WR_CAUSE_DIAG,&diag) < 0)
- return(-1);
- debug(F100,"X.25 reset","",0);
- return(0);
- }
- /* Clear X.25 virtual circuit */
- int
- x25clear() {
- int i;
- debug(F100,"X.25 clear","",0);
- bzero ((char *)&diag,sizeof(diag));
- diag.flags = (1 << DIAG_TYPE);
- diag.datalen = 2;
- diag.data[0] = 0;
- diag.data[1] = 0;
- ioctl (ttyfd,X25_WR_CAUSE_DIAG,&diag); /* Send Clear Request */
- return(ttclos(0)); /* Close socket */
- }
- /* X.25 status */
- int
- x25stat() {
- if (ttyfd == -1) return (-1);
- return(0);
- }
- /* Set Q_BIT on */
- VOID
- setqbit() {
- static int qbiton = 1 << Q_BIT;
- ioctl (ttyfd,X25_SEND_TYPE,&qbiton);
- }
- /* Set Q_BIT off */
- VOID
- resetqbit() {
- static int qbitoff = 0;
- ioctl (ttyfd,X25_SEND_TYPE,&qbitoff);
- }
- /* Read n characters from X.25 circuit into buf */
- int
- x25xin(n,buf) int n; CHAR *buf; {
- register int x, c;
- int qpkt;
- do {
- x = read(ttyfd,buf,n);
- if (buf[0] & (1 << Q_BIT)) { /* If Q_BIT packet, process it */
- /* If return -1 : invitation to clear; -2 : PAD changes */
- if ((c=qbitpkt(buf+1,x-2)) < 0) return(c);
- qpkt = 1;
- } else qpkt = 0;
- } while (qpkt);
- #ifdef COMMENT /* Disabled by Stephen Riehm 19.12.97 */
- /* BUG!
- * if buf[] is full, then this null lands in nirvana!
- * I was unable to find any code which needs a trailing null in buf[]
- */
- if (x > 0) buf[x] = '\0';
- #endif /* COMMENT */
- if (x < 1) x = -1;
- debug(F101,"x25xin x","",x);
- return(x);
- }
- #ifdef COMMENT /* NO LONGER NEEDED! */
- /* X.25 read a line */
- int
- #ifdef PARSENSE
- #ifdef CK_ANSIC
- x25inl(CHAR *dest, int max,int timo, CHAR eol, CHAR start)
- #else
- x25inl(dest,max,timo,eol,start) int max,timo; CHAR *dest, eol, start;
- #endif /* CK_ANSIC */
- #else /* not PARSENSE */
- #ifdef CK_ANSIC
- x25inl(CHAR *dest, int max,int timo, CHAR eol)
- #else
- x25inl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
- #endif /* __SDTC__ */
- #endif /*PARSENSE */
- /* x25inl */ {
- CHAR *pdest;
- int pktype, goteol, rest, n;
- int i, flag = 0;
- extern int ttprty, ttpflg;
- int ttpmsk;
- ttpmsk = (ttprty) ? 0177 : 0377; /* Set parity stripping mask */
- debug(F101,"x25inl max","",max);
- debug(F101,"x25inl eol","",eol);
- pdest = dest;
- rest = max;
- goteol = 0;
- do {
- n = read(ttyfd,pdest,rest);
- n--;
- pktype = *pdest & 0x7f;
- switch (pktype) {
- case 1 << Q_BIT:
- if (qbitpkt(pdest+1,--n) < 0) return(-2);
- break;
- default:
- if (flag == 0) { /* if not in packet, search start */
- for (i = 1; (i < n) &&
- !(flag = ((dest[i] & 0x7f) == start));
- i++);
- if (flag == 0) { /* not found, discard junk */
- debug(F101,"x25inl skipping","",n);
- continue;
- } else { /* found, discard junk before start */
- int k;
- n = n - i + 1;
- for (k = 1; k <= n; k++, i++) dest[k] = dest[i];
- }
- }
- for (i = 0; (i < n) && /* search for eol */
- !(goteol=(((*pdest = *(pdest+1)&ttpmsk)&0x7f)== eol));
- i++,pdest++);
- *pdest = '\0';
- rest -= n;
- }
- } while ((rest > 0) && (!goteol));
- if (goteol) {
- n = max - rest;
- debug (F111,"x25inl X.25 got",(char *) dest,n);
- if (timo) ttimoff();
- if (ttpflg++ == 0 && ttprty == 0) {
- if ((ttprty = parchk(dest,start,n)) > 0) {
- int j;
- debug(F101,"x25inl senses parity","",ttprty);
- debug(F110,"x25inl packet before",(char *)dest,0);
- ttpmsk = 0x7f;
- for (j = 0; j < n; j++)
- dest[j] &= 0x7f; /* Strip parity from packet */
- debug(F110,"x25inl packet after ",dest,0);
- } else {
- debug(F101,"parchk","",ttprty);
- if (ttprty < 0) { ttprty = 0; n = -1; }
- }
- }
- ttimoff();
- return(n);
- }
- ttimoff();
- return(-1);
- }
- #endif /* COMMENT */
- #endif /* SUNX25 */
- #ifdef IBMX25
- /*
- * IBM X25 support - using the NPI streams interface
- * written by Stephen Riehm, pc-plus, Munich Germany
- */
- /* riehm: missing functions / TODO list */
- /*
- x25intr() - Send an interrupt packet
- */
- /* return an error message depending on packet type */
- char *
- x25err(n) int n; {
- static char buf[30];
- switch (n) {
- case NBADADDR: return "invalid address";
- case NBADOPT: return "invalid options";
- case NACCESS: return "no permission";
- case NNOADDR: return "unable to allocate address";
- case NOUTSTATE: return "invalid state";
- case NBADSEQ: return "invalid sequence number";
- case NSYSERR: return "system error";
- case NBADDATA: return "invalid data size";
- case NBADFLAG: return "invalid flag";
- case NNOTSUPPORT: return "unsupported primitive";
- case NBOUND: return "address in use";
- case NBADQOSPARAM: return "bad QOS parameters";
- case NBADQOSTYPE: return "bad QOS type";
- case NBADTOKEN: return "bad token value";
- case NNOPROTOID: return "protocol id could not be allocated";
- case NODDCUD: return "odd length call user data";
- default:
- ckmakmsg(buf,sizeof(buf),"Unknown NPI error ",ckitoa(n),NULL,NULL);
- return buf;
- }
- }
- /* turn a meaningless primitive number into a meaningful primitive name */
- char *
- x25prim(n) int n; {
- static char buf[30];
- switch(n) {
- case N_BIND_ACK: return "N_BIND_ACK";
- case N_BIND_REQ: return "N_BIND_REQ";
- case N_CONN_CON: return "N_CONN_CON";
- case N_CONN_IND: return "N_CONN_IND";
- case N_CONN_REQ: return "N_CONN_REQ";
- case N_CONN_RES: return "N_CONN_RES";
- case N_DATACK_IND: return "N_DATAACK_IND";
- case N_DATACK_REQ: return "N_DATAACK_REQ";
- case N_DATA_IND: return "N_DATA_IND";
- case N_DATA_REQ: return "N_DATA_REQ";
- case N_DISCON_IND: return "N_DISCON_IND";
- case N_DISCON_REQ: return "N_DISCON_REQ";
- case N_ERROR_ACK: return "N_ERROR_ACK";
- case N_EXDATA_IND: return "N_EXDATA_IND";
- case N_EXDATA_REQ: return "N_EXDATA_REQ";
- case N_INFO_ACK: return "N_INFO_ACK";
- case N_INFO_REQ: return "N_INFO_REQ";
- case N_OK_ACK: return "N_OK_ACK";
- case N_OPTMGMT_REQ: return "N_OPTMGMT_REQ";
- case N_RESET_CON: return "N_RESET_CON";
- case N_RESET_IND: return "N_RESET_IND";
- case N_RESET_REQ: return "N_RESET_REQ";
- case N_RESET_RES: return "N_RESET_RES";
- case N_UDERROR_IND: return "N_UDERROR_IND";
- case N_UNBIND_REQ: return "N_UNBIND_REQ";
- case N_UNITDATA_REQ: return "N_UNITDATA_REQ";
- case N_UNITDATA_IND: return "N_UNITDATA_IND";
- default:
- ckmakmsg(buf,sizeof(buf),"UNKNOWN (",ckitoa(n),")",NULL);
- return buf;
- }
- }
- /*****************************************************************************
- * Function: x25getmsg()
- * Description: get a STREAMS message, and check it for errors
- *
- * Parameters:
- * fd - file descriptor to x25 device (opened)
- * control - control buffer (pre-allocated)
- * ctl_size - size of control buffer
- * data - data buffer (pre-allocated)
- * data_size - size of data buffer
- * flags - flags for getmsg()
- * expected - expected Primitive type
- *
- * Return Value:
- * >= 0 OK (size of data returned)
- * -1 error
- *
- */
- int
- x25getmsg( fd, control, ctl_size, data, data_size, get_flags, expected )
- int fd; /* X25 device (opened) */
- N_npi_ctl_t *control; /* control buffer (pre-allocated) */
- int ctl_size; /* size of control buffer */
- N_npi_data_t *data; /* data buffer (pre-allocated) */
- int data_size; /* size of data buffer */
- int *get_flags; /* getmsg() flags */
- int expected; /* expected primitive type */
- /* x25getmsg */ {
- int rc = 0; /* return code */
- struct strbuf *get_ctl=NULL; /* getmsg control */
- struct strbuf *get_data=NULL; /* getmsg data */
- int more = 0; /* flag for more data etc */
- int file_status = -1; /* file async status */
- N_npi_ctl_t * result; /* pointer to simplify switch() */
- int packet_type = -1; /* unknown packet thus far */
- #ifdef TRACE
- printf( "TRACE: entering x25getmsg\n" );
- #endif /* TRACE */
- debug( F110, "x25getmsg waiting for packet ", x25prim( expected ), 0);
- /* prepare the control structures for getmsg */
- if (control) {
- if ((get_ctl = (struct strbuf*)malloc(sizeof(struct strbuf))) == NULL)
- {
- perror("kermit x25getmsg(): get_ctl malloc failed\n");
- debug( F100, "x25getmsg malloc failed for get_ctl\n", "", 0);
- return(-1);
- }
- /* allow getmsg to return an unexpected packet type (which may be
- * larger than the expected one)
- */
- get_ctl->maxlen = NPI_MAX_CTL;
- get_ctl->len = 0;
- get_ctl->buf = (char *)control;
- } else {
- printf(
- "kermit x25getmsg(): internal error. control buffer MUST be pre-allocated!\n"
- );
- debug(F100,"x25getmsg internal error. no buffer pre-allocated","",0);
- return( -1 );
- }
- if (data) {
- if ((get_data = (struct strbuf*)malloc(sizeof(struct strbuf))) == NULL)
- {
- perror("kermit x25getmsg(): get_data malloc failed\n");
- debug( F100, "x25getmsg malloc failed for get_data\n", "", 0);
- return(-1);
- }
- get_data->maxlen = (NPI_MAX_DATA < data_size ) ?
- NPI_MAX_DATA :
- data_size;
- get_data->len = 0;
- get_data->buf = (char *)data;
- }
- /* get an X.25 packet -
- * it may be any kind of packet, so check for special cases
- * it may be split into multiple parts - so loop if necessary
- */
- do {
- #ifdef DEBUG
- printf( "kermit: x25getmsg(): getting a message\n" );
- #endif /* DEBUG */
- errno = 0;
- if ((more = getmsg(fd, get_ctl, get_data, get_flags)) < 0) {
- #ifdef DEBUG
- printf( "kermit: x25getmsg(): getmsg returned an error\n" );
- perror( "getmsg error was" );
- #endif /* DEBUG */
- debug(F101, "x25getmsg getmsg returned an error\n", "", errno);
- if ((errno == EAGAIN) && (get_data && (get_data->len > 0)) ) {
- /* was in non-blocking mode, nothing to get, but we're
- * already waiting for the rest of the packet -
- * switch to blocking mode for the next read.
- * file_status used to reset file status before returning
- */
- if ((file_status = fcntl(fd, F_GETFL, 0)) < 0
- || fcntl(fd, F_SETFL, file_status & ~O_NDELAY) < 0)
- {
- perror("x25getmsg(): couldn't change x25 blocking mode");
- debug(F101,
- "x25getmsg fcntl returned an error\n", "", errno);
- /* netclos(); */
- rc = -1;
- break;
- } else {
- /* loop again into a blocking getmsg() */
- continue;
- }
- } else {
- /* no data to get in non-blocking mode - return empty handed */
- perror( "x25getmsg(): getmsg failed" );
- debug(F101,"x25getmsg getmsg returned an error\n", "", errno);
- rc = -1;
- break;
- }
- } else if (more & MORECTL) {
- /* panic - the control information was larger than the
- * maximum control buffer size!
- */
- /* riehm: close connection? */
- #ifdef DEBUG
- printf("x25getmsg(): received partial control packet - panic\n");
- #endif /* DEBUG */
- debug( F101, "x25getmsg getmsg bad control block\n", "", errno);
- rc = -1;
- break;
- }
- if (result = (N_npi_ctl_t *)control) {
- packet_type = result->bind_ack.PRIM_type;
- if (packet_type != N_OK_ACK) {
- x25lastmsg = packet_type;
- }
- }
- #ifdef DEBUG
- /* printf( "kermit: x25getmsg(): getting " ); */
- if (get_ctl->len > 0) {
- x25dump_prim(result);
- }
- debug(F110,
- "x25getmsg got packet ",
- x25prim( result->bind_ack.PRIM_type ),
- 0
- );
- #endif /* DEBUG */
- if (get_ctl->len >= (int)sizeof(result->bind_ack.PRIM_type)) {
- /* not as pretty as a switch(), but switch can't handle
- * runtime variable values :-(
- */
- if (packet_type == expected ) {
- /* got what we wanted, special case for DATA_IND
- * packets though */
- /* riehm: check Q-bit ? */
- #ifdef DEBUG
- printf("x25getmsg(): got expected packet\nrc is %d\n", rc);
- #endif /* DEBUG */
- if (packet_type == N_DATA_IND ) {
- /* data received. May be incomplete, even though
- * getmsg returned OK
- */
- if (result->data_ind.DATA_xfer_flags & N_MORE_DATA_FLAG)
- more |= MOREDATA;
- if (result->data_ind.DATA_xfer_flags & N_RC_FLAG)
- printf( "x25getmsg(): data packet wants ack\n" );
- }
- } else if( packet_type == N_DISCON_IND) {
- printf( "X25 diconnected\n" );
- /* riehm: need to acknowledge a disconnection? */
- x25clear();
- /* x25unbind( ttyfd ); */
- rc = -1;
- } else if( packet_type == N_ERROR_ACK) {
- errno = result->error_ack.UNIX_error;
- perror( "X25 error received" );
- rc = -1;
- } else {
- printf("x25getmsg(): failed %s\n", x25err(packet_type));
- rc = -1;
- }
- }
- #ifdef COMMENT
- else {
- /* Panic - no control data */
- printf( "kermit: x25getmsg(): no control data with packet\n" );
- rc = -1;
- }
- #endif /* COMMENT */
- if (get_data && (get_data->len >= 0)) {
- get_data->buf += get_data->len;
- get_data->maxlen -= get_data->len;
- }
- } while ((rc == 0)
- && (get_data && (get_data->maxlen > 0))
- && (more & MOREDATA)
- );
- /* return the file status to its original value, unless its still
- * set to -1, or one of the fcntl's failed */
- if ((file_status >= 0) && fcntl(fd, F_SETFL, file_status) < 0)
- rc = -1;
- /*
- * Verify that we received an expected primitive
- * there is apparantly an error case where the primitive is set
- * correctly, but there is not enough data in the control structure
- */
- if ((packet_type != expected) && (get_ctl->len >= ctl_size) ) {
- fprintf(stderr,
- "x25getmsg(): %s NOT received. Primitive received was %s\n",
- x25prim( expected ), x25prim( packet_type ));
- debug(F110, "x25getmsg got an unexpected packet ",
- x25prim(packet_type),
- 0
- );
- rc = -1;
- }
- if (rc == 0) {
- if (get_data && ( get_data->len >= 0)) {
- rc = get_data->len;
- }
- }
- if (get_ctl) { free(get_ctl); get_ctl = NULL; }
- if (get_data) { free(get_data); get_data = NULL; }
- #ifdef COMMENT
- #ifdef DEBUG
- printf( "kermit x25getmsg(): returning %d\n", rc );
- #endif /* DEBUG */
- #endif /* COMMENT */
- debug(F110, "x25getmsg returning packet ", x25prim( packet_type ), 0);
- #ifdef TRACE
- printf( "TRACE: leaving x25getmsg\n" );
- #endif /* TRACE */
- return(rc);
- }
- /*****************************************************************************
- * Function: x25putmsg()
- *
- * Description:
- * send a message to a X25 STREAM
- *
- * Parameters:
- * fd - file descriptor to x25 device (opened)
- * control - control buffer (pre-allocated)
- * data - data buffer (pre-allocated)
- * data_len - length of data to be transmitted
- * put_flags - flags for putmsg()
- *
- * Return Value:
- * >= 0 number of bytes transmitted
- * -1 error
- */
- int
- x25putmsg(fd, control, data, data_len, put_flags)
- int fd; /* X25 device (opened) */
- N_npi_ctl_t *control; /* control buffer (pre-allocated) */
- N_npi_data_t *data; /* data buffer (pre-allocated) */
- int data_len; /* length of data (not the size of
- the buffer) */
- int *put_flags; /* putmsg() flags */
- /* x25putmsg */ {
- int rc = 0; /* return code */
- ulong type; /* primitive type */
- struct strbuf *put_ctl = NULL; /* putmsg control */
- struct strbuf *put_data = NULL; /* putmsg data */
- #ifdef TRACE
- printf( "TRACE: entering x25putmsg\n" );
- #endif /* TRACE */
- #ifdef DEBUG
- printf( "kermit: x25putmsg(): putting " );
- x25dump_prim( control );
- printf( "\tdata:\t\t" );
- x25dump_data( data, 0, data_len );
- debug(F110,"x25putmsg: putting packet ",x25prim(control->PRIM_type),0);
- #endif /* DEBUG */
- if (control) {
- put_ctl = (struct strbuf *)malloc( sizeof( struct strbuf ) );
- if (put_ctl == NULL) {
- perror("kermit x25putmsg(): put_ctl malloc failed\n");
- return(-1);
- }
- put_ctl->maxlen = 0; /* unused by putmsg */
- put_ctl->len = NPI_MAX_CTL;
- put_ctl->buf = (char *)control;
- }
- if (data && ( data_len > 0)) {
- put_data = (struct strbuf *)malloc( sizeof( struct strbuf ) );
- if( put_data == NULL) {
- perror("kermit x25putmsg(): put_data malloc failed\n");
- return(-1);
- }
- put_data->maxlen = 0; /* unused by putmsg */
- put_data->len = data_len;
- put_data->buf = (char *)data;
- }
- errno = 0;
- rc = putmsg (fd, put_ctl, put_data, 0);
- if (rc < 0) {
- printf("x25putmsg(): couldn't put %s\n",x25prim(control->PRIM_type));
- perror("kermit: x25putmsg(): putmsg failed");
- return(-1);
- }
- /* riehm: this should perhaps be discounted! */
- x25lastmsg = control->PRIM_type;
- #ifdef COMMENT
- #ifdef DEBUG
- printf( "kermit debug: x25putmsg() returning %d\n", data_len );
- #endif /* DEBUG */
- #endif /* COMMENT */
- debug( F101, "x25putmsg block size put ", "", data_len);
- #ifdef TRACE
- printf( "TRACE: leaving x25putmsg\n" );
- #endif /* TRACE */
- return( data_len );
- }
- /*****************************************************************************
- * Function: x25bind
- * Description: The bind submitted to NPI provides the information required
- * by the packet layer for it to listen for suitable incoming
- * calls.
- *
- * WARNING:
- *
- * This routine needs to be called in a completely different manner for
- * the client and server side. When starting a client, the
- * num_waiting_calls and CUD information should all be set to 0! The
- * client's CUD must be inserted in the CONN_REQ data block.
- * When starting a server, the CUD must be set to a CUD pattern, and
- * the number of waiting calls should be set to a number other than 0.
- * (num waiting calls is the number of incomming calls which are to be
- * put on hold while the server is servicing another client.)
- *
- * Who invented this crap?
- *
- * Parameters:
- * fd - X25 device (opened)
- * addr - local address
- * cud - User Data (null terminated)
- * cud_len - User Data length
- * num_waiting_calls - number of outstanding calls allowed on this stream
- * line - logical port number (1)
- * flags - 0, DEFAULT_LISTENER or TOKEN_REQUEST
- *
- * Return Value:
- * if binding is successful, 0 is returned for a client, and a token is
- * returned for a server
- *
- * Return code: 0 if successful
- * -1 if unsuccessful
- *****************************************************************************/
- ulong
- x25bind(fd, addr, cud, cud_len, num_waiting_calls, line, bind_flags)
- int fd; /* X25 device (opened) */
- char * addr; /* local address */
- char * cud; /* Call User Data (null terminated) */
- int cud_len; /* User Data length */
- int num_waiting_calls; /* Outstanding calls allowed */
- int line; /* logical port number */
- ulong bind_flags; /* 0, DEFAULT_LISTENER or TOKEN_REQUEST */
- /* x25bind */ {
- ulong rc; /* return code */
- int get_flags; /* priority flag passed to getmsg */
- int put_flags = 0; /* output flags for putmsg, always 0 */
- ulong type; /* primitive type */
- N_bind_req_t *bind_req; /* pointer to N_BIND_REQ primitive */
- N_bind_ack_t *bind_ack; /* pointer to N_BIND_ACK primitive */
- char *addtl_info; /* pointer to info in addition to
- * the N_BIND_REQ primitive that is
- * passed in the control structure
- * to putmsg */
- int addr_len = 0; /* length of address string */
- ulong bind_req_t_size; /* for debugging only */
- #ifdef TRACE
- printf("TRACE: entering x25bind\n" );
- #endif /* TRACE */
- #ifdef DEBUG
- printf("TRACE: x25bind( %d, %s, %s, %d, %d )\n",
- fd, addr, cud, line, bind_flags
- );
- #endif /* DEBUG */
- /*
- * Allocate and zero out space to hold the control portion of the
- * message passed to putmsg. This will contain the N_BIND_REQ
- * primitive and any additional info required for that.
- *
- * Note: allocated space is the size of the union typedef
- * N_npi_ctl_t to allow the use fo the generic x25putmsg routine.
- */
- bind_req = (N_bind_req_t *) malloc(sizeof( N_npi_ctl_t));
- if (bind_req == NULL) {
- perror("kermit: x25bind(): bind_req malloc failed");
- debug(F100, "x25bind bind_req malloc failed", "", 0);
- return(-1);
- }
- bzero((char *)bind_req, sizeof(N_npi_ctl_t));
- /* Build the Bind Request Primitive */
- bind_req->PRIM_type = (ulong) N_BIND_REQ;
- /* Note that the address length is n+2 and NOT n. Two bytes MUST preceed
- * the actual address in an N_BIND_REQ. The first byte contains the
- * line number being used with this address, and the second byte is the
- * X.121 address prefix, which must be zero.
- */
- addr_len = strlen(addr);
- bind_req->ADDR_length = (ulong) (addr_len + 2);
- bind_req->ADDR_offset = (ulong)(sizeof(N_bind_req_t));
- bind_req->CONIND_number = (ulong)num_waiting_calls; /* server only */
- bind_req->BIND_flags = (ulong) bind_flags; /* 0 in client */
- bind_req->PROTOID_length = (ulong) cud_len; /* 0 in client */
- if (cud_len == 0) {
- bind_req->PROTOID_offset = (ulong) 0;
- } else {
- /* need to remember the trailing NULL in the address - not
- * counted in the address length
- */
- bind_req->PROTOID_offset
- = (ulong) (sizeof(N_bind_req_t) + bind_req->ADDR_length);
- }
- /*
- * Now fill in the additional information required with this primitive
- * (address and protocol information (Call User Data))
- */
- addtl_info = (char *) ((void *)bind_req + bind_req->ADDR_offset);
- /*
- * The bitwise "&" ensures that the line number is only one byte long
- */
- *addtl_info++ = (char) line & 0xff;
- *addtl_info++ = (char) 0; /* X.121 format */
- bcopy( addr, addtl_info, addr_len ); /* include trailing null */
- addtl_info += addr_len;
- if (cud_len > 0)
- bcopy( cud, addtl_info, cud_len );
- /*
- * Call putmsg() to put the bind request message on the stream
- */
- if (x25putmsg(fd,
- (N_npi_ctl_t*)bind_req,
- (N_npi_data_t *)NULL,
- 0,
- &put_flags
- ) < 0) {
- printf( "kermit: x25bind(): x25putmsg failed\n" );
- return(-1);
- }
- /*
- * Allocate and zero out space for the N_BIND_ACK primitive
- */
- bind_ack = (N_bind_ack_t *) malloc(sizeof(N_npi_ctl_t));
- if (bind_ack == NULL){
- perror("kermit: x25bind(): bind_ack malloc failed");
- return(-1);
- }
- bzero(bind_ack, sizeof(N_npi_ctl_t));
- /*
- * Initialize the control structure and flag variable sent to getmsg
- */
- get_flags=0;
- /* get the ACK for the bind */
- #ifdef DEBUG
- printf( "kermit: x25bind() trying to get a BIND_ACK\n" );
- #endif /* DEBUG */
- rc = (ulong)x25getmsg( fd, (N_npi_ctl_t*)bind_ack,
- (int)sizeof( N_bind_ack_t ), (N_npi_data_t*)NULL, 0, &get_flags,
- N_BIND_ACK );
- /* turn quantitive return code into a qualitative one */
- if (rc > 0) rc = 0;
- /* if all went well, get the token from the acknowledgement packet */
- if ((bind_flags & TOKEN_REQUEST ) && ( rc >= 0)) {
- rc = bind_ack->TOKEN_value;
- }
- /* free up the memory we allocated earlier */
- free(bind_req);
- free(bind_ack);
- #ifdef TRACE
- printf( "TRACE: leaving x25bind\n" );
- #endif /* TRACE */
- return( rc );
- }
- /*****************************************************************************
- * Function: x25call
- * Description: This routine builds and sends an N_CONN_REQ primitive, then
- * checks for an N_CONN_CON primitive in return.
- *
- * Parameters:
- * fd - file descriptor of stream
- * caddr - called address (remote address)
- *
- * Functions Referenced:
- * malloc()
- * bzero()
- * getmsg()
- * putmsg()
- *
- * Return code:
- * 0 - if successful
- * -1 if not successful
- *****************************************************************************/
- int
- x25call(fd, remote_nua, cud)
- int fd; /* X25 device (opened) */
- char * remote_nua; /* remote address to call */
- char * cud; /* call user data */
- /* x25call */ {
- int rc; /* return code */
- int flags; /* Connection flags */
- int get_flags; /* priority flags for getmsg */
- ulong type; /* primitive type */
- N_conn_req_t *connreq_ctl; /* pointer to N_CONN_REQ primitive */
- N_npi_data_t *connreq_data; /* pointer to N_CONN_REQ data (CUD) */
- int connreq_data_len; /* length of filled data buffer */
- N_conn_con_t *conncon_ctl; /* pointer to N_CONN_CON primitive */
- N_npi_data_t *conncon_data; /* pointer to any data associated with
- * the N_CONN_CON primitive */
- char *addtl_info; /* pointer to additional info needed
- * for N_CONN_REQ primitive */
- int addr_len; /* length of address */
- #ifdef TRACE
- printf( "TRACE: entering x25call\n" );
- #endif /* TRACE */
- #ifdef DEBUG
- printf( "x25call( %d, %s )\n", fd, remote_nua );
- printf( "connecting to %s on fd %d\n", remote_nua, fd );
- #endif /* DEBUG */
- /*
- * Allocate and zero out space for the N_CONN_REQ primitive
- * use the size of the generic NPI primitive control buffer
- */
- connreq_ctl = (N_conn_req_t *) malloc(sizeof(N_npi_ctl_t));
- if (connreq_ctl == NULL){
- perror("kermit: x25call(): connreq_ctl malloc failed");
- return(-1);
- }
- bzero(connreq_ctl,sizeof(N_npi_ctl_t));
- /*
- * Build the Connection Request Primitive
- */
- flags = 0;
- connreq_ctl->PRIM_type = (ulong) N_CONN_REQ;
- /* Note that the address length is nchai+1 and not n+2. The line number
- * is only passed with the address for the bind. The first byte of
- * the address for the N_CONN primitives contains the X.121
- * address prefix, which must be zero. The remaining bytes are the
- * address itself.
- */
- addr_len = strlen( remote_nua );
- connreq_ctl->DEST_length = (ulong) (addr_len + 1);
- connreq_ctl->DEST_offset = (ulong) sizeof(N_conn_req_t);
- /* connreq_ctl->CONN_flags = (ulong)EX_DATA_OPT | REC_CONF_OPT; */
- connreq_ctl->CONN_flags = (ulong) 0;
- connreq_ctl->QOS_length = (ulong) 0; /* unsupported in AIX 4.1 */
- connreq_ctl->QOS_offset = (ulong) 0; /* unsupported in AIX 4.1 */
- addtl_info = (char *) ((void*)connreq_ctl + connreq_ctl->DEST_offset);
- *addtl_info++ = (char) 0; /* X.121 format */
- bcopy( remote_nua, addtl_info, addr_len );
- /*
- * setup the data buffer for the connection request
- */
- connreq_data = (N_npi_data_t *) malloc(sizeof(N_npi_data_t));
- if (connreq_data == NULL){
- perror("kermit: x25call(): connreq_data malloc failed");
- return(-1);
- }
- bzero(connreq_data,sizeof(N_npi_data_t));
- /* facility selection needs to be put in the front of connreq_data */
- connreq_data_len = 0;
- connreq_data_len += x25facilities( (char *)connreq_data );
- if (cud && *cud) {
- bcopy(cud,
- (char *)((char *)connreq_data + connreq_data_len),
- strlen(cud)
- );
- connreq_data_len += strlen( cud );
- }
- /*
- * Call putmsg() to put the connection request message on the stream
- */
- rc = x25putmsg( fd, (N_npi_ctl_t*)connreq_ctl, connreq_data,
- connreq_data_len, &flags );
- if (rc < 0) {
- return(-1);
- }
- /*
- * Allocate and zero out space for the N_CONN_CON primitive
- */
- if ((conncon_ctl = (N_conn_con_t *) malloc(sizeof(N_npi_ctl_t))) == NULL) {
- perror("kermit: x25call(): conncon_ctl malloc failed");
- return(-1);
- }
- bzero(conncon_ctl, sizeof(N_npi_ctl_t));
- /*
- * Allocate and zero out space for any data associated with N_CONN_CON
- */
- if ( (conncon_data = (N_npi_data_t *) malloc(NPI_MAX_DATA)) == NULL) {
- perror("kermit: x25call(): conncon_data malloc failed");
- return(-1);
- }
- bzero(conncon_data, NPI_MAX_DATA);
- /* Initialize and build the structures for getmsg */
- get_flags=0;
- rc = x25getmsg( fd, (N_npi_ctl_t*)conncon_ctl, (int)sizeof( N_conn_con_t ),
- conncon_data, NPI_MAX_DATA, &get_flags, N_CONN_CON );
- /* turn quantitive return code into a qualitative one */
- if (rc > 0) rc = 0;
- /* Free the space that we no longer need */
- if (connreq_ctl) { free(connreq_ctl); connreq_ctl = NULL; }
- if (conncon_ctl) { free(conncon_ctl); conncon_ctl = NULL; }
- if (conncon_data) { free(conncon_data); conncon_data = NULL; }
- #ifdef TRACE
- printf( "TRACE: leaving x25call\n" );
- #endif /* TRACE */
- return(rc);
- }
- /*****************************************************************************
- * Function: x25getcall
- *
- * Description: This routine checks for an incomming call, verified
- * that it is a CONNIND (connection indication) message, and then
- * accepts the call and returns the file descriptor of the new stream
- *
- * Parameters:
- * fd - file descriptor of listening stream
- *
- * Return Codes:
- * callfd - file descriptor of connected incomming call.
- * - set to -1 if an error occured
- *
- *****************************************************************************/
- int
- x25getcall(fd) int fd; {
- int x25callfd; /* fd of incomming call */
- N_conn_ind_t *connind_ctl; /* connind controll buffer */
- N_npi_data_t *connind_data; /* connind data buffer */
- int get_flags; /* flags for getmsg */
- ulong flags; /* connection flags */
- int rc; /* return code */
- extern x25addr_t remote_nua; /* remote X.25 addr global var */
- #ifdef TRACE
- printf( "TRACE: entering x25getcall\n" );
- #endif /* TRACE */
- /* allocate space for connection indication buffers */
- if ((connind_ctl = (N_conn_ind_t *)malloc(sizeof(N_npi_ctl_t))) == NULL) {
- perror("kermit: x25getcall(): connind_ctl malloc failed");
- return (-1);
- }
- bzero(connind_ctl, sizeof(N_npi_ctl_t));
- if ((connind_data = (N_npi_data_t *)malloc(NPI_MAX_DATA)) == NULL) {
- perror("kermit: x25getcall(): connind_data malloc failed");
- return (-1);
- }
- bzero(connind_data, NPI_MAX_DATA);
- /* initialise control structures */
- get_flags = 0;
- /* call getmsg to check for a connection indication */
- if (x25getmsg(fd,
- (N_npi_ctl_t*)connind_ctl,
- (int)sizeof(N_conn_ind_t),
- connind_data,
- NPI_MAX_DATA,
- &get_flags,
- N_CONN_IND
- ) < 0) {
- #ifdef DEBUG
- printf( "x25getcall(): errno is: %d\n", errno );
- #endif /* DEBUG */
- perror ("x25getcall(): getmsg failed");
- return(-1);
- }
- /* a connection indication was received
- * - pull it to bits and answer the call
- */
- x25seqno = connind_ctl->SEQ_number;
- flags = connind_ctl->CONN_flags;
- #ifdef DEBUG
- printf( "setting remote_nua to a new value due to incomming call\n" );
- #endif /* DEBUG */
- /*
- * no guarantee that the address is null terminated, ensure that
- * after copying that it is (assumption: remote_nua is longer than
- * the address + 1)
- */
- bzero(remote_nua, sizeof(remote_nua));
- /* note: connind_ctl contains a x121 address, which has a null as
- * the FIRST character - strip it off!
- */
- ckstrncpy(remote_nua,
- (char*)((char*)connind_ctl + connind_ctl->SRC_offset + 1),
- connind_ctl->SRC_length - 1
- );
- #ifdef DEBUG
- printf( "remote_nua set to new value of %s\n", remote_nua );
- #endif /* DEBUG */
- /* errors handled by callee */
- x25callfd = x25accept(x25seqno, flags);
- /* free the malloc'd buffers */
- if (connind_ctl) { free(connind_ctl); connind_ctl = NULL; }
- if (connind_data) { free(connind_data); connind_data = NULL; }
- #ifdef TRACE
- printf( "TRACE: leaving x25getcall\n" );
- #endif /* TRACE */
- /* return the file descriptor (or error if < 0) */
- return( x25callfd );
- }
- /*****************************************************************************
- * Function: x25accept
- *
- * Description: accept an incomming call
- * This essentially means opening a new STREAM and sending
- * an acknowledge back to the caller.
- *
- * Parameters:
- * seqno - sequence number for acknowledgement
- * flags - flags passed to us by the caller
- *
- * Return Codes:
- * fd - file descriptor of new STREAM
- * set to -1 if an error occured
- *
- *****************************************************************************/
- int
- x25accept(seqno,flags)
- ulong seqno; /* connection sequence number */
- ulong flags; /* connection flags */
- /* x25accept */ {
- int x25callfd; /* fd for incomming call */
- int get_flags; /* priority flags for getmsg */
- int put_flags = 0; /* flags for putmsg, always 0 */
- int addr_len; /* length of local address */
- ulong token; /* connection token */
- N_conn_res_t *conn_res; /* N_CONN_RES primitive */
- N_ok_ack_t *ok_ack; /* N_OK_ACK primitive */
- char *addtl_info; /* temp pointer */
- int rc; /* temporary return code */
- /* global variables from ckcmai.c */
- extern int revcall, closgr, cudata;
- extern char udata[];
- extern x25addr_t local_nua; /* local X.25 address */
- extern char x25name[]; /* x25 device name (sx25a0) */
- extern char x25dev[]; /* x25 device file /dev/x25pkt */
- extern int x25port; /* logical port to use */
- ulong bind_flags = 0; /* flags for binding the X25 stream */
- #ifdef TRACE
- printf( "TRACE: entering x25accept\n" );
- #endif /* TRACE */
- /* open a new packet level stream */
- if ((x25callfd = open(x25dev, O_RDWR)) < 0) {
- perror ("kermit: x25accept(): X.25 device open error");
- debug(F101,"x25accept() device open error","",errno);
- return(-1);
- }
- /* push the NPI onto the STREAM */
- if (ioctl(x25callfd,I_PUSH,"npi") < 0) {
- perror( "kermit: x25accept(): couldn't push npi on the X25 stream" );
- debug(F101,"x25accept can't push npi on the X25 stream","",errno);
- return (-1);
- }
- /* bind kermit server to the local X25 address */
- /* taken from /usr/samples/sx25/npi/npiserver.c (AIX 4) */
- bind_flags |= TOKEN_REQUEST;
- token = x25bind(x25callfd,local_nua,(char *)NULL,0,0,x25port,bind_flags);
- if (token < 0) {
- printf( "kermit: x25accept(): couldn't bind to local X25 address\n" );
- netclos();
- return(-1);
- }
- /* allocate connection response primitive */
- if ((conn_res = (N_conn_res_t *)malloc( NPI_MAX_CTL )) == NULL) {
- perror("kermit: x25accept(): conn_res malloc failed");
- return (-1);
- }
- bzero((char *)conn_res, NPI_MAX_CTL);
- /* setup connection response primitive */
- addr_len = strlen( local_nua );
- conn_res->PRIM_type = (ulong)N_CONN_RES;
- conn_res->TOKEN_value = token;
- /* note address length is n+1 to accomodate the X.121 address prefix */
- conn_res->RES_length = (ulong)(addr_len + 1);
- conn_res->RES_offset = (ulong)sizeof( N_conn_res_t );
- conn_res->SEQ_number = seqno;
- conn_res->CONN_flags = 0;
- conn_res->QOS_length = 0; /* unsupported - must be 0 (!?) */
- conn_res->QOS_offset = 0;
- addtl_info = (char *)((char *)conn_res + conn_res->RES_offset);
- *addtl_info++ = (char)0; /* X.121 address prefix */
- bcopy( local_nua, addtl_info, addr_len );
- /*
- * send off the connect response
- */
- if (x25putmsg(x25callfd,
- (N_npi_ctl_t*)conn_res,
- (N_npi_data_t *)NULL,
- 0,
- &put_flags
- ) < 0 ) {
- perror("kermit: x25accept(): putmsg connect response failed");
- return(-1);
- }
- /*
- * Allocate and zero out space for the OK_ACK primitive
- */
- if ((ok_ack = (N_ok_ack_t *) malloc(sizeof(N_npi_ctl_t))) == NULL) {
- perror("kermit: x25call(): ok_ack malloc failed");
- return(-1);
- }
- bzero(ok_ack, sizeof(N_npi_ctl_t));
- /* Initialize and build the structures for getmsg */
- get_flags=0;
- rc = (int)x25getmsg(x25callfd,
- (N_npi_ctl_t*)ok_ack,
- (int)sizeof(N_ok_ack_t),
- (N_npi_data_t*)NULL,
- 0,
- &get_flags,
- N_OK_ACK
- );
- if (rc == 0) {
- /* sequence number is only for disconnecting when not connected !? */
- x25seqno = 0;
- }
- /* free up malloc'ed buffer space */
- if (conn_res) { free(conn_res); conn_res = NULL; }
- if (ok_ack) { free(ok_ack); ok_ack = NULL; }
- #ifdef TRACE
- printf( "TRACE: leaving x25accept\n" );
- #endif /* TRACE */
- return( ( rc >= 0 ) ? x25callfd : -1 );
- }
- /*****************************************************************************
- * Function: x25unbind
- *
- * Description: This subroutine builds and sends an unbind request and gets
- * the acknowledgement for it.
- *
- * Parameters:
- * fd - File descriptor of the stream
- *
- * Functions Referenced:
- * getmsg()
- * putmsg()
- * malloc()
- * bzero()
- *
- * Return code:
- * 0 - if successful
- * -1 - if not successful
- *****************************************************************************/
- int
- x25unbind(fd) int fd; { /* X25 device (opened) */
- int rc; /* return code */
- int flags; /* bind flags */
- int get_flags; /* priority flag for getmsg */
- ulong type; /* primitive type */
- N_unbind_req_t *unbind_req; /* pointer to N_UNBIND_REQ */
- N_ok_ack_t *ok_ack; /* pointer to N_OK_ACK */
- #ifdef TRACE
- printf( "TRACE: entering x25unbind\n" );
- #endif /* TRACE */
- #ifdef DEBUG
- /* printf( "x25unbind( %d )\n", fd ); */
- #endif /* DEBUG */
- debug(F101,"x25unbind closing x25 connection #","",fd);
- /* Allocate and zero out space to hold the N_UNBIND_REQ primitive */
- unbind_req = (N_unbind_req_t *) malloc(sizeof(N_npi_ctl_t));
- if (unbind_req == NULL) {
- perror("kermit: x25unbind(): unbind_req malloc failed");
- return(-1);
- }
- bzero(unbind_req, sizeof(N_npi_ctl_t));
- /*
- * Build the Unbind Request Primitive
- */
- flags = 0;
- unbind_req->PRIM_type = (ulong) N_UNBIND_REQ;
- /*
- * Call putmsg() to put the bind request message on the stream
- */
- if (x25putmsg(fd,
- (N_npi_ctl_t*)unbind_req,
- (N_npi_data_t *)NULL,
- 0,
- &flags
- ) < 0) {
- perror ("kermit: x25unbind(): putmsg failed");
- return(-1);
- }
- /* Allocate and Zero out space for the N_OK_ACK primitive */
- ok_ack = (N_ok_ack_t *) malloc(sizeof(N_npi_ctl_t));
- if (ok_ack == NULL) {
- perror("kermit x25unbind(): ok_ack malloc failed\n");
- return(-1);
- }
- bzero(ok_ack, sizeof(N_npi_ctl_t));
- /* Initialize and build the control structure for getmsg */
- get_flags=0;
- /* Call getmsg() to check for an acknowledgement */
- rc = x25getmsg(fd,
- (N_npi_ctl_t*)ok_ack,
- (int)sizeof(N_ok_ack_t),
- (N_npi_data_t*)NULL,
- 0,
- &get_flags,
- N_OK_ACK
- );
- if (rc < 0) {
- perror ("kermit: x25unbind: getmsg failed");
- return(-1);
- }
- /* Free up the space that we no longer need */
- if (unbind_req) { free(unbind_req); unbind_req = NULL; }
- if (ok_ack) { free(ok_ack); ok_ack = NULL; }
- #ifdef TRACE
- printf( "TRACE: leaving x25unbind\n" );
- #endif /* TRACE */
- return(0);
- }
- /*****************************************************************************
- * Function: x25xin
- *
- * Description:
- * Read n characters from X.25 circuit into buf (AIX only)
- *
- * Parameters:
- * data_buf_len maximum size of data buffer
- * data_buf pointer to pre-allocated buffer space
- *
- * Return Value:
- * the number of characters actually read
- */
- int
- x25xin(data_buf_len,data_buf) int data_buf_len; CHAR *data_buf; {
- struct strbuf getmsg_ctl; /* streams control structure */
- struct strbuf getmsg_data; /* streams data structure */
- int rc = 0; /* return code */
- int getmsg_flags; /* packet priority flags */
- char * ctl_buf; /* npi control buffer */
- N_npi_ctl_t * result; /* pointer to simplify switch() */
- #ifdef TRACE
- printf( "TRACE: entering x25xin\n" );
- #endif /* TRACE */
- /* ensure that no maximum's are overridden */
- data_buf_len = (NPI_MAX_DATA < data_buf_len) ? NPI_MAX_DATA : data_buf_len;
- /* allocate space for packet control info */
- if ((ctl_buf = (char *)malloc(NPI_MAX_CTL)) == NULL) {
- perror( "kermit: x25xin(): ctl_buf malloc" );
- return(-1);
- }
- #ifdef COMMENT
- /* riehm: need zeroed buffer for getmsg? */
- bzero( ctl_buf, NPI_MAX_CTL );
- /* clear data buffer */
- bzero( data_buf, data_buf_len );
- #endif /* COMMENT */
- getmsg_flags = 0; /* get the first packet available */
- rc = x25getmsg(ttyfd,
- ctl_buf,
- NPI_MAX_CTL,
- data_buf,
- data_buf_len,
- &getmsg_flags,
- N_DATA_IND
- );
- #ifdef COMMENT
- #ifdef DEBUG
- if (rc >= 0) {
- printf( "kermit: x25xin(): got " );
- x25dump_data( data_buf, 0, rc );
- } else {
- printf( "x25xin(): attempt to get data resulted in an error\n" );
- }
- #endif /* DEBUG */
- #endif /* COMMENT */
- /* free buffers */
- if (ctl_buf) { free(ctl_buf); ctl_buf = NULL; }
- #ifdef TRACE
- printf( "TRACE: leaving x25xi\n" );
- #endif /* TRACE */
- return(rc);
- }
- /*****************************************************************************
- * Function: x25write
- *
- * Description:
- * write a block of characters to the X25 STREAM (AIX)
- *
- * Parameters:
- * fd file descriptor to write to
- * databuf buffer containing data to write
- * databufsize size of the buffer to write
- *
- * Return Value:
- * size the number of bytes actually transmitted
- */
- int
- x25write(fd, databuf, databufsize)
- int fd; /* X25 STREAMS file descriptor (ttyfd) */
- char *databuf; /* buffer to write */
- int databufsize; /* buffer size */
- /* x25write */ {
- N_data_req_t *data_req_ctl;
- int rc; /* return code (size transmitted) */
- int write_flags = 0; /* always 0 !? */
- #ifdef TRACE
- printf( "TRACE: entering x25write\n" );
- #endif /* TRACE */
- if ((data_req_ctl = (N_data_req_t *)malloc(NPI_MAX_CTL) ) == NULL) {
- perror( "kermit: x25write(): data_req_ctl malloc" );
- return(-1);
- }
- data_req_ctl->PRIM_type = N_DATA_REQ;
- data_req_ctl->DATA_xfer_flags = 0;
- /* riehm: possible extension
- * possibly need to think about splitting up the data buffer
- * into multiple parts if databufsize > NPI_MAX_DATA
- */
- #ifdef COMMENT
- #ifdef DEBUG
- printf( "kermit: x25write(): writing data to x25 stream\n" );
- printf( "\tdata:\t" );
- x25dump_data(databuf, 0, databufsize);
- #endif /* DEBUG */
- #endif /* COMMENT */
- rc = x25putmsg(fd,
- (N_npi_ctl_t*)data_req_ctl,
- (N_npi_data_t*)databuf,
- databufsize,
- &write_flags
- );
- if (data_req) { free(data_req_ctl); data_req = NULL; }
- #ifdef TRACE
- printf( "TRACE: leaving x25write\n" );
- #endif /* TRACE */
- return(rc);
- }
- /*****************************************************************************
- * Function: x25local_nua
- *
- * Description:
- * This routine is only interesting for IBM computers. In order
- * to set up a connection (see x25bind()) you need to know the
- * local NUA (x25 address). Unfortunately, you need all this code
- * to find that out, I just hope this works for everyone else!
- *
- * Parameters:
- * a pre-allocated character buffer, long enough to hold an X.25 address
- * and the tailing null.
- *
- * Return Value:
- * the length of the address string.
- * 0 = error
- */
- int
- x25local_nua(char *buf) {
- struct CuAt *response; /* structure to fill with info from ODM */
- CLASS_SYMBOL retClass; /* ODM class */
- char query[64]; /* odm database query */
- int rc = 0; /* return value (length of local NUA) */
- extern char x25name[]; /* x25 device name (sx25a0) */
- #ifdef TRACE
- printf( "TRACE: entering x25local_nua\n" );
- #endif /* TRACE */
- /* set up query string */
- if (x25name[0] == '\0') {
- #ifdef DEBUG
- printf( "kermit: x25local_nua(): No x25 device set, trying sx25a0\n" );
- #endif /* DEBUG */
- strcpy( x25name, "sx25a0" );
- }
- ckmakmsg(query, sizeof(query), "name like ",x25name,
- " and attribute like local_nua");
- /* initialise ODM database */
- odmerrno = 0;
- if (odm_initialize() == -1) {
- printf( "x25local_nua(): can't initialize ODM database");
- switch (odmerrno) {
- case ODMI_INVALID_PATH:
- printf( "invalid path\n" );
- break;
- case ODMI_MALLOC_ERR:
- printf( "malloc failed\n" );
- break;
- default:
- printf( "unknown error %d\nPlease call IBM\n", odmerrno );
- }
- return(rc);
- }
- /* open the CuAt class */
- retClass = odm_open_class(CuAt_CLASS);
- if (((int)retClass) == -1) {
- printf( "kermit: x25local_nua(): can't open CuAt class in odm. " );
- switch (odmerrno) {
- case ODMI_CLASS_DNE:
- printf( "CuAt class doesn't exist\n" );
- break;
- case ODMI_CLASS_PERMS:
- printf( "permission to CuAt class file denied\n" );
- break;
- case ODMI_MAGICNO_ERR:
- printf( "CuAt is an invalid ODM object class\n" );
- break;
- case ODMI_OPEN_ERR:
- printf( "cannot open CuAt class - and don't know why!\n" );
- break;
- case ODMI_INVALID_PATH:
- printf( "invalid path\n" );
- break;
- case ODMI_TOOMANYCLASSES:
- printf( "too many object classes have been opened\n" );
- break;
- default:
- printf( "unknown error %d\nPlease call IBM\n", odmerrno );
- }
- return(rc);
- }
- #ifdef DEBUG
- printf("retClass= %d\n", retClass);
- #endif /* DEBUG */
- response = (struct CuAt *)odm_get_first( retClass, query, NULL );
- if (((int)response) == -1) {
- printf( "kermit: x25local_nua(): odm query failed " );
- switch (odmerrno) {
- case ODMI_BAD_CRIT: /* Programming error */
- printf( "bad search criteria\n" );
- break;
- case ODMI_CLASS_DNE:
- printf( "CuAt class doesn't exist\n" );
- break;
- case ODMI_CLASS_PERMS:
- printf( "permission to CuAt class file denied\n" );
- break;
- case ODMI_INTERNAL_ERR:
- printf("odm internal error\nPlease contact your administrator\n" );
- break;
- case ODMI_INVALID_CLXN:
- printf("CuAt is invalid or inconsistent odm class collection\n");
- break;
- case ODMI_INVALID_PATH:
- printf( "invalid path\n" );
- break;
- case ODMI_MAGICNO_ERR:
- printf( "CuAt is an invalid ODM object class\n" );
- break;
- case ODMI_MALLOC_ERR:
- printf( "malloc failed\n" );
- break;
- case ODMI_OPEN_ERR:
- printf( "cannot open CuAt class - and don't know why!\n" );
- break;
- case ODMI_TOOMANYCLASSES:
- printf( "too many object classes have been opened\n" );
- break;
- default:
- printf( "unknown error %d\nPlease call IBM\n", odmerrno );
- }
- return(rc);
- }
- /* check for a meaningfull response */
- if (response != NULL) {
- if (response->value != NULL) {
- strcpy(buf, response->value);
- rc = strlen( buf );
- #ifdef DEBUG
- /*
- printf( "attribute name is: %s\n", (char *)response->attribute );
- printf( "I think my address is %s\n", (char*)response->value );
- */
- #endif /* DEBUG */
- } else {
- printf( "kermit: x25local_nua(): couldn't find the local NUA\n" );
- }
- } else {
- switch (odmerrno) {
- case ODMI_BAD_CRIT:
- printf( "Error: ODMI_BAD_CRIT - bad criteria\n" );
- break;
- case ODMI_CLASS_DNE:
- printf( "Error: ODMI_CLASS_DNE - class doesn't exist\n" );
- break;
- case ODMI_CLASS_PERMS:
- printf( "Error: ODMI_CLASS_PERMS - class permissions\n" );
- break;
- case ODMI_INTERNAL_ERR:
- printf( "Error: ODMI_INTERNAL_ERR - panic\n" );
- break;
- case ODMI_INVALID_CLXN:
- printf( "Error: ODMI_INVALID_CLXN - invalid collection\n" );
- break;
- case ODMI_INVALID_PATH:
- printf( "Error: ODMI_INVALID_PATH - invalid path - what path?\n" );
- break;
- case ODMI_MAGICNO_ERR:
- printf( "Error: ODMI_MAGICNO_ERR - invalid object magic\n" );
- break;
- case ODMI_MALLOC_ERR:
- printf( "Error: ODMI_MALLOC_ERR - malloc failed\n" );
- break;
- case ODMI_OPEN_ERR:
- printf( "Error: ODMI_OPEN_ERR - cannot open class\n" );
- break;
- case ODMI_TOOMANYCLASSES:
- printf( "Error: ODMI_TOOMANYCLASSES - too many classes\n" );
- break;
- default:
- printf( "Unknown error!\n" );
- }
- return(rc);
- }
- /* close the database again */
- odm_close_class( retClass );
- /* forget about ODM all together */
- odm_terminate();
- #ifdef TRACE
- printf( "TRACE: leaving x25local_nua\n" );
- #endif /* TRACE */
- debug(F110, "x25local_nua local address is ", buf, 0);
- return(rc);
- }
- /*****************************************************************************
- * Function: x25facilities
- *
- * Description:
- * build up the facilities data packet for a connection request
- *
- * Parameters:
- * a pre-allocated char buffer, normally NPI_MAX_DATA big.
- *
- * Return Value:
- * the number of characters inserted into the buffer
- */
- int
- x25facilities(buffer) char *buffer; {
- extern int revcall;
- extern int closgr;
- char *p; /* temp pointer */
- char *start; /* temp pointer */
- #ifdef TRACE
- printf( "TRACE: entering x25facilities\n" );
- #endif /* TRACE */
- p = buffer + 1;
- start = p;
- #ifdef DEBUG
- printf( "kermit: x25facilities(): getting X25 facilities\n" );
- #endif /* DEBUG */
- if (revcall != 0) {
- #ifdef DEBUG
- printf("reverse charge: %d\n", revcall );
- #endif /* DEBUG */
- *++p = 0x01;
- *++p = revcall;
- }
- if (closgr > 0) {
- #ifdef DEBUG
- printf("closed user group: %d\n", closgr );
- #endif /* DEBUG */
- *++p = 0x03;
- *++p = closgr;
- }
- #ifdef DEBUG
- if (p == start) {
- printf( "no facilities\n" );
- }
- #endif /* DEBUG */
- /* set the size of the facilities buffer */
- *buffer = (char)( p - start ) & 0xff;
- #ifdef DEBUG
- printf( "kermit: x25facilities(): returning %d\n", (int)(p - buffer) );
- #endif /* DEBUG */
- #ifdef TRACE
- printf( "TRACE: leaving x25facilities\n" );
- #endif /* TRACE */
- /* return the size of the facilities with size byte */
- /* 1 == no facilities, 0 byte returned as facilities size */
- return( (int)(p - buffer) );
- }
- /*
- * reset the connection
- */
- int
- x25reset(cause, diagn) char cause; char diagn; {
- /* not implemented */
- #ifdef TRACE
- printf( "TRACE: entering x25reset\n" );
- #endif /* TRACE */
- #ifdef TRACE
- printf( "TRACE: leaving x25reset\n" );
- #endif /* TRACE */
- return(0);
- }
- /*
- * clear the x25 connection - ie: hang up
- */
- int
- x25clear() {
- int get_flags = 0; /* priority flag for getmsg */
- int put_flags = 0; /* send flags, always 0 */
- ulong type; /* primitive type */
- N_discon_req_t *discon_req; /* pointer to N_DISCON_REQ */
- N_discon_ind_t *discon_ind; /* pointer to N_DISCON_IND */
- N_npi_data_t *discon_data; /* pointer to N_DISCON_IND data */
- int rc = 0; /* return code */
- #ifdef TRACE
- printf( "TRACE: entering x25clear\n" );
- #endif /* TRACE */
- #ifdef DEBUG
- /* printf( "x25clear(): checking last msg: %s\n", x25prim(x25lastmsg)); */
- #endif /* DEBUG */
- /*
- * The following checks are used to ensure that we don't disconnect
- * or unbind twice - this seems to throw the NPI interface right out of
- * kilter.
- */
- switch(x25lastmsg) {
- case N_BIND_ACK:
- case N_CONN_CON:
- case N_CONN_REQ:
- case N_DATA_REQ:
- case N_DATA_IND:
- {
- #ifdef DEBUG
- /* printf("x25clear(): actively disconnecting\n"); */
- #endif /* DEBUG */
- discon_req = (N_discon_req_t *)malloc(NPI_MAX_CTL);
- if (discon_req == NULL) {
- perror("kermit x25clear(): discon_req malloc failed\n");
- /* fallthrough, try to unbind the NPI anyway */
- } else {
- discon_req->PRIM_type = N_DISCON_REQ;
- discon_req->DISCON_reason = 0; /* not used by AIX */
- discon_req->RES_length = 0;
- discon_req->RES_offset = (ulong)(sizeof(N_discon_req_t));
- discon_req->SEQ_number = x25seqno; /* global */
- if (x25putmsg(ttyfd,
- (N_npi_ctl_t*)discon_req,
- (N_npi_data_t*)NULL,
- 0,
- &put_flags
- ) < 0) {
- perror("x25putmsg failed in x25clear()");
- }
- discon_ind = (N_discon_ind_t *)malloc(NPI_MAX_CTL);
- discon_data = (N_npi_data_t *)malloc(NPI_MAX_DATA);
- if((discon_ind == NULL) || (discon_data == NULL)) {
- perror("x25clear(): discon_ind malloc failed\n");
- /* fallthrough, try to unbind the NPI anyway */
- } else {
- if(x25getmsg(ttyfd,
- (N_npi_ctl_t*)discon_ind,
- NPI_MAX_CTL,
- (N_npi_data_t*)discon_data,
- NPI_MAX_DATA,
- &get_flags,
- N_OK_ACK
- ) < 0 ) {
- perror("x25getmsg failed in x25clear()");
- /* fallthrough, try to unbind the NPI anyway */
- }
- }
- }
- break;
- }
- }
- if (x25lastmsg != N_UNBIND_REQ) {
- rc = x25unbind(ttyfd);
- }
- #ifdef TRACE
- printf( "TRACE: leaving x25clear\n" );
- #endif /* TRACE */
- return(rc);
- }
- #ifdef DEBUG
- /*
- * only for debugging
- *
- * turn the internal representation of a datablock into something
- * half-way readable. Because the length is known, we can print
- * the string including null's etc (important, because the first(!)
- * byte of an X121 address is a null! (X121 addr == 0 + X25 addr)
- */
- x25dump_data(char *addr, ulong offset, ulong length) {
- char *ptr = addr + offset;
- ulong i = length;
- /* allocate enough memory for all unprintable chars */
- char *buf = (char *)malloc( length * 4 );
- char *bptr = buf; /* pointer to current place in the print buffer */
- while (i > 0) {
- if (isprint(*ptr)) {
- *bptr++ = *ptr;
- } else {
- *bptr++ = '[';
- strcpy(bptr,ckctox(*ptr,1)); bptr += 2;
- *bptr++ = ']';
- }
- ptr++;
- i--;
- }
- if (length > 0) {
- *bptr = '\0';
- printf( "%s", buf );
- }
- printf( " (%d+%d)\n", offset, length );
- if (buf) { free(buf); buf = NULL; }
- return;
- }
- /*
- * only for debugging
- * print as much useful information about a packet as possible
- */
- x25dump_prim(primitive) N_npi_ctl_t *primitive; {
- printf("Primitive");
- switch (primitive->PRIM_type) {
- case N_BIND_ACK:
- printf( "\tN_BIND_ACK\n\taddress:\t" );
- x25dump_data( (char *)primitive,
- primitive->bind_ack.ADDR_offset,
- primitive->bind_ack.ADDR_length );
- printf( "\tproto id:\t" );
- x25dump_data( (char *)primitive,
- primitive->bind_ack.PROTOID_offset,
- primitive->bind_ack.PROTOID_length );
- printf( "\tconnind:\t%d\n\ttoken:\t\t%d\n",
- primitive->bind_ack.CONIND_number,
- primitive->bind_ack.TOKEN_value );
- break;
- case N_BIND_REQ:
- printf( "\tN_BIND_REQ\n\taddress:\t" );
- x25dump_data( (char *)primitive,
- primitive->bind_req.ADDR_offset,
- primitive->bind_req.ADDR_length );
- printf( "\tproto id:\t" );
- x25dump_data( (char *)primitive,
- primitive->bind_req.PROTOID_offset,
- primitive->bind_req.PROTOID_length );
- printf( "\tconnind:\t%d\n\tflags:\t\t%d\n",
- primitive->bind_req.CONIND_number,
- primitive->bind_req.BIND_flags );
- break;
- case N_CONN_CON:
- printf( "\tN_CONN_CON\n" );
- printf( "\tRES\t\t" );
- x25dump_data( (char *)primitive,
- primitive->conn_con.RES_offset,
- primitive->conn_con.RES_length );
- printf( "\tflags:\t%d\n", primitive->conn_con.CONN_flags );
- break;
- case N_CONN_IND:
- printf( "\tN_CONN_IND\n" );
- printf( "\tsource:\t\t" );
- x25dump_data( (char *)primitive,
- primitive->conn_ind.SRC_offset,
- primitive->conn_ind.SRC_length );
- printf( "\tdestination:\t" );
- x25dump_data( (char *)primitive,
- primitive->conn_ind.DEST_offset,
- primitive->conn_ind.DEST_length );
- printf( "\tSEQ_number:\t%d\n", primitive->conn_ind.SEQ_number );
- printf( "\tflags:\t%d\n", primitive->conn_ind.CONN_flags );
- break;
- case N_CONN_REQ:
- printf( "\tN_CONN_REQ\n\tdestination:\t" );
- x25dump_data( (char *)primitive,
- primitive->conn_req.DEST_offset,
- primitive->conn_req.DEST_length );
- printf( "\tflags:\t%d\n", primitive->conn_req.CONN_flags );
- break;
- case N_CONN_RES:
- printf( "\tN_CONN_RES\n" );
- printf( "\tTOKEN_value\t%d\n", primitive->conn_res.TOKEN_value );
- printf( "\tSEQ_number\t%d\n", primitive->conn_res.SEQ_number );
- printf( "\tCONN_flags\t%d\n", primitive->conn_res.CONN_flags );
- printf( "\tRES\t\t" );
- x25dump_data( (char *)primitive,
- primitive->conn_res.RES_offset,
- primitive->conn_res.RES_length );
- break;
- case N_DATACK_IND:
- printf( "\tN_DATACK_IND\n" );
- break;
- case N_DATACK_REQ:
- printf( "\tN_DATACK_REQ\n" );
- printf( "\tflags:\t%d\n", primitive->data_req.DATA_xfer_flags );
- break;
- case N_DATA_IND:
- printf( "\tN_DATA_IND\n" );
- printf( "\tflags:\t%d\n", primitive->data_ind.DATA_xfer_flags );
- break;
- case N_DATA_REQ:
- printf( "\tN_DATA_REQ\n" );
- break;
- case N_DISCON_IND:
- printf( "\tN_DISCON_IND\n" );
- printf( "\torigin:\t%d\n", primitive->discon_ind.DISCON_orig );
- printf( "\treason:\t\t%d\n", primitive->discon_ind.DISCON_reason );
- printf( "\tseq no:\t\t%d\n", primitive->discon_ind.SEQ_number );
- printf( "\tRES:\t" );
- x25dump_data( (char *)primitive,
- primitive->discon_ind.RES_offset,
- primitive->discon_ind.RES_length );
- break;
- case N_DISCON_REQ:
- printf( "\tN_DISCON_REQ\n" );
- printf( "\tDISCON_reason:\t%d\n",
- primitive->discon_req.DISCON_reason );
- printf( "\tRES:\t" );
- x25dump_data( (char *)primitive,
- primitive->discon_req.RES_offset,
- primitive->discon_req.RES_length );
- printf( "\tSEQ_number:\t%d\n", primitive->discon_req.SEQ_number );
- break;
- case N_ERROR_ACK:
- printf( "\tN_ERROR_ACK\n" );
- printf( "\tCaused by:\t%s\n",
- x25prim( primitive->error_ack.ERROR_prim ) );
- printf( "\tNPI error:\t%s\n",
- x25err( primitive->error_ack.NPI_error ));
- errno = primitive->error_ack.UNIX_error;
- perror( "\t" );
- break;
- case N_EXDATA_IND:
- printf( "\tN_EXDATA_ACK\n" );
- break;
- case N_EXDATA_REQ:
- printf( "\tN_EXDATA_REQ\n" );
- break;
- case N_INFO_ACK:
- printf( "\tN_INFO_ACK\n" );
- printf( "\tNSDU size:\t%d\n", primitive->info_ack.NSDU_size );
- printf( "\tENSDU size:\t%d\n", primitive->info_ack.ENSDU_size );
- printf( "\tCDATA size:\t%d\n", primitive->info_ack.CDATA_size );
- printf( "\tDDATA size:\t%d\n", primitive->info_ack.DDATA_size );
- printf( "\tADDR size:\t%d\n", primitive->info_ack.ADDR_size );
- printf( "\tNIDU size:\t%d\n", primitive->info_ack.NIDU_size );
- break;
- case N_INFO_REQ:
- printf( "\tN_INFO_REQ\n" );
- break;
- case N_OK_ACK:
- printf( "\tN_OK_ACK\n" );
- break;
- case N_OPTMGMT_REQ:
- printf( "\tN_OPTMGMT_REQ\n" );
- break;
- case N_RESET_CON:
- printf( "\tN_RESET_CON\n" );
- break;
- case N_RESET_IND:
- printf( "\tN_RESET_IND\n" );
- printf( "\treason:\t\t%d\n", primitive->reset_ind.RESET_reason );
- printf( "\torigin:\t\t%d\n", primitive->reset_ind.RESET_orig );
- break;
- case N_RESET_REQ:
- printf( "\tN_RESET_REQ\n" );
- printf( "\treason:\t\t%d\n", primitive->reset_req.RESET_reason );
- break;
- case N_RESET_RES:
- printf( "\tN_RESET_RES\n" );
- break;
- case N_UDERROR_IND:
- printf( "\tN_UDERROR_IND\n" );
- break;
- case N_UNBIND_REQ:
- printf( "\tN_UNBIND_REQ\n" );
- break;
- case N_UNITDATA_REQ:
- printf( "\tN_UNITDATA_REQ\n" );
- break;
- case N_UNITDATA_IND:
- printf( "\tN_UNITDATA_IND\n" );
- break;
- default:
- (void) printf( "Unknown NPI error %d", primitive->PRIM_type );
- return 0;
- }
- }
- #endif /* DEBUG */
- /* it looks like signal handling is not needed with streams! */
- /* x25oobh() - handle SIGURG signals - take from isode ? */
- #endif /* IBMX25 */
- #ifndef NOHTTP
- /*
- Which time.h files to include... See ckcdeb.h for defaults.
- Note that 0, 1, 2, or all 3 of these can be included according to
- the symbol definitions.
- */
- #ifndef NOTIMEH
- #ifdef TIMEH
- #include <time.h>
- #endif /* TIMEH */
- #endif /* NOTIMEH */
- #ifndef NOSYSTIMEH
- #ifdef SYSTIMEH
- #include <sys/time.h>
- #endif /* SYSTIMEH */
- #endif /* NOSYSTIMEH */
- #ifndef NOSYSTIMEBH
- #ifdef SYSTIMEBH
- #include <sys/timeb.h>
- #endif /* SYSTIMEBH */
- #endif /* NOSYSTIMEBH */
- #ifndef TIMEH
- #ifndef SYSTIMEH
- #ifndef SYSTIMEBH
- #ifdef Plan9
- #include <sys/time.h>
- #else
- #ifdef AIX41
- #include <time.h>
- #else
- #ifdef SUNOS4
- #include <sys/time.h>
- #else
- #ifdef SYSTIMEH
- #include <sys/time.h>
- #else
- #ifdef POSIX
- #include <posix/time.h>
- #else
- #ifdef CLIX
- #include <sys/time.h>
- #else
- #ifdef OS2
- #include <time.h>
- #else
- #include <time.h>
- /* #include <utime.h> */
- #endif /* OS2 */
- #endif /* CLIX */
- #endif /* POSIX */
- #endif /* SYSTIMEH */
- #endif /* SUNOS4 */
- #endif /* AIX41 */
- #endif /* Plan9 */
- #endif
- #endif
- #endif
- #ifdef OS2
- #include <sys/utime.h>
- #ifdef NT
- #define utimbuf _utimbuf
- #endif /* NT */
- #define utime _utime
- #else
- #ifdef SYSUTIMEH /* <sys/utime.h> if requested, */
- #include <sys/utime.h> /* for extra fields required by */
- #else /* 88Open spec. */
- #ifdef UTIMEH /* or <utime.h> if requested */
- #include <utime.h> /* (SVR4, POSIX) */
- #define SYSUTIMEH /* Use this for both cases. */
- #endif /* UTIMEH */
- #endif /* SYSUTIMEH */
- #endif /* OS2 */
- #ifdef VMS /* SMS 2007/02/15 */
- #include "ckvrtl.h"
- #endif /* def VMS */
- #ifndef HTTP_VERSION
- #define HTTP_VERSION "HTTP/1.1"
- #endif /* HTTP_VERSION */
- #ifdef CMDATE2TM
- time_t
- #ifdef CK_ANSIC
- http_date(char * date)
- #else
- http_date(date) char * date;
- #endif /* CK_ANSIC */
- /* http_date */ {
- /* HTTP dates are of the form: "Sun, 06 Oct 1997 20:11:47 GMT" */
- /* There are two older formats which we are required to parse
- * that we currently do not:
- *
- * RFC 850: "Sunday, 06-Oct-97 20:11:47 GMT"
- * asctime(): "Sun Nov 6 20:11:47 1997"
- *
- * However, it is required that all dates be sent in the form we
- * do accept. The other two formats are for compatibility with
- * really old servers.
- */
- extern char cmdatebuf[18];
- struct tm t_tm;
- time_t t;
- char ldate[32];
- int j;
- j = ckindex(",",date,0,0,0);
- ckstrncpy(ldate,&date[j+1],25);
- { /*
- cmcvtate() date changed to return a string pointer.
- fdc, 12 Aug 2001.
- */
- char * dp;
- dp = (char *)cmcvtdate(ldate,0); /* Convert to normal form */
- if (!dp)
- return(0);
- t_tm = *cmdate2tm(dp,1);
- }
- /*
- From Lucas Hart, 5 Dec 2001:
- "On the systems to which I have access (SunOS 4.1.1, Solaris 8, and Tru64),
- setting tm_isdst to -1 maintains the correct timezone offsets, i.e., writes
- the specified (GMT) time if the buffer size is 21, or the contemporaneous
- localtime if the buffer size is 25. Perhaps tm_isdst should be set in
- cmdate2tm(), rather than only in http_date."
- */
- #ifndef NOTM_ISDST /* For platforms where */
- t_tm.tm_isdst = -1; /* tm_isdst doesn't exist. */
- #endif /* NOTM_ISDST */
- t = mktime(&t_tm); /* NOT PORTABLE */
- #ifdef XX_TIMEZONE
- t -= _timezone;
- #endif /* XX_TIMEZONE */
- return(t);
- }
- #endif /* CMDATE2TM */
- char *
- http_now() {
- static char nowstr[32];
- #ifdef CMDATE2TM
- struct tm *gmt;
- time_t ltime; /* NOT PORTABLE */
- time(<ime);
- gmt = gmtime(<ime); /* PROBABLY NOT PORTABLE */
- strftime(nowstr,32,"%a, %d %b %Y %H:%M:%S GMT",gmt); /* NOT PORTABLE */
- /* not only is it not portable but it's locale-dependent */
- #else
- /*
- This is hopeless. First of all, it seems that HTTP wants Day and Month
- NAMES? In English? Whose idea was that? Even worse, the date/time must be
- expressed in Zulu (UTC (GMT)), and converting from local time to GMT is a
- nightmare. Every platform does it differently, if at all -- even if we
- restrict ourselves to UNIX. For example (quoting from recent C-Kermit edit
- history), "Fixed a longstanding bug in the BSDI version, in which incoming
- file dates were set in GMT rather than local time. It seems in 4.4BSD,
- localtime() does not return the local time, but rather Zero Meridian (Zulu)
- time (GMT), and must be adjusted by the tm_gmtoff value." Swell. For
- greater appreciation of the scope of the problem, just take a look at the
- time-related #ifdefs in ckutio.c. The only right way to do this is to add
- our own portable API for converting between local time and GMT/UTC/Zulu
- that shields us not only from UNIXisms like time_t and struct tm, but also
- the unbelievable amount of differences in time-related APIs -- e.g. is
- "timezone" an external variable or a function; which header file(s) do we
- include, etc etc etc. It's a major project.
- */
- int x;
- x = cmcvtdate("",1);
- Evidently this code is not used -- if it is, it must be fixed to use
- new (aug 2001) cmcvtdate() calling conventions.
- if (x < 0)
- return("");
- /* yyyymmdd hh:mm:ss */
- /* 01234567890123456 */
- nowstr[0] = 'X'; /* 1st letter of day */
- nowstr[1] = 'x'; /* 2nd letter of day */
- nowstr[2] = 'x'; /* 3rd letter of day */
- nowstr[3] = ',';
- nowstr[4] = ' ';
- nowstr[5] = cmdate[6];
- nowstr[6] = cmdate[7];
- nowstr[7] = ' ';
- nowstr[8] = ' '; /* first letter of month */
- nowstr[9] = ' '; /* second letter of month */
- nowstr[10] = ' '; /* third letter of month */
- nowstr[11] = ' ';
- nowstr[12] = cmdate[0];
- nowstr[13] = cmdate[1];
- nowstr[14] = cmdate[2];
- nowstr[15] = cmdate[3];
- nowstr[16] = ' ';
- nowstr[17] = cmdate[9];
- nowstr[18] = cmdate[10];
- nowstr[19] = cmdate[11];
- nowstr[20] = cmdate[12];
- nowstr[21] = cmdate[13];
- nowstr[22] = cmdate[14];
- nowstr[23] = cmdate[15];
- nowstr[24] = cmdate[16];
- nowstr[25] = ' ';
- nowstr[26] = 'G';
- nowstr[27] = 'M';
- nowstr[28] = 'T';
- nowstr[29] = '\0';
- #endif /* CMDATE2TM */
- return(nowstr);
- }
- #ifndef OS2
- #ifndef CK_AUTHENTICATION
- /* from ckuusr.h, which this module normally doesn't include */
- _PROTOTYP( int dclarray, (char, int) );
- #endif /* CK_AUTHENTICATION */
- #endif /* OS2 */
- /*
- Assign http response pairs to given array.
- For best results, response pairs should contain no spaces.
- Call with:
- resp = pointer to response list.
- n = size of response list.
- array = array letter.
- Returns:
- 0 on failure.
- >= 1, size of array, on success.
- */
- static int
- #ifdef CK_ANSIC
- http_mkarray(char ** resp, int n, char array)
- #else
- http_mkarray(resp, n, array) char ** resp; int n; char array;
- #endif /* CK_ANSIC */
- {
- #ifndef NOSPL
- int i, x;
- char ** ap;
- extern char ** a_ptr[];
- extern int a_dim[];
- if (!array || n <= 0)
- return(0);
- if ((x = dclarray(array,n)) < 0) {
- printf("?Array declaration failure\n");
- return(-9);
- }
- /* Note: argument array is 0-based but Kermit array is 1-based */
- ap = a_ptr[x];
- ap[0] = NULL; /* 0th element is empty */
- for (i = 1; i <= n; i++) {
- ap[i] = resp[i-1]; /* If resp elements were malloc'd */
- resp[i-1] = NULL;
- }
- a_dim[x] = n;
- return(n);
- #else
- return(0);
- #endif /* NOSPL */
- }
- #define HTTPHEADCNT 64
- int
- http_get_chunk_len()
- {
- int len = 0;
- int i = 0, j = -1;
- char buf[24];
- int ch;
- while ((ch = http_inc(0)) >= 0 && i < 24) {
- buf[i] = ch;
- if ( buf[i] == ';' ) /* Find chunk-extension (if any) */
- j = i;
- if ( buf[i] == 10 ) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- buf[i] = '\0';
- break;
- }
- i++;
- }
- if ( i < 24 ) { /* buf now contains len in Hex */
- len = hextoulong(buf, j == -1 ? i : j-1);
- }
- return(len);
- }
- int
- http_isconnected()
- {
- return(httpfd != -1);
- }
- char *
- http_host()
- {
- return(httpfd != -1 ? http_host_port : "");
- }
- char *
- http_security()
- {
- if ( httpfd == -1 )
- return("NULL");
- #ifdef CK_SSL
- if (tls_http_active_flag) {
- SSL_CIPHER * cipher;
- const char *cipher_list;
- static char buf[128];
- buf[0] = NUL;
- cipher = SSL_get_current_cipher(tls_http_con);
- cipher_list = SSL_CIPHER_get_name(cipher);
- SSL_CIPHER_description(cipher,buf,sizeof(buf));
- return(buf);
- }
- #endif /* CK_SSL */
- return("NULL");
- }
- int
- http_reopen()
- {
- int rc = 0;
- char * s = NULL; /* strdup is not portable */
- if ( tcp_http_proxy ) {
- char * p;
- makestr(&s,(char *)http_host_port);
- p = s;
- while (*p != '\0' && *p != ':') p++; /* Look for colon */
- if (*p == ':') { /* Have a colon */
- *p++ = '\0'; /* Get service name or number */
- } else {
- p="http";
- }
- rc = http_open(s,p,http_ssl,NULL,0,http_agent);
- } else {
- makestr(&s,(char *)http_ip);
- rc = http_open(s,ckuitoa(http_port),http_ssl,NULL,0,http_agent);
- }
- free(s);
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- http_open(char * hostname, char * svcname, int use_ssl, char * rdns_name,
- int rdns_len, char * agent)
- #else /* CK_ANSIC */
- http_open(hostname, svcname, use_ssl, rdns_name, rdns_len, agent)
- char * hostname;
- char * svcname;
- int use_ssl;
- char * rdns_name;
- int rdns_len;
- char * agent;
- #endif /* CK_ANSIC */
- {
- char namecopy[NAMECPYL];
- char *p;
- int i, x, dns = 0;
- #ifdef TCPSOCKET
- int isconnect = 0;
- #ifdef SO_OOBINLINE
- int on = 1;
- #endif /* SO_OOBINLINE */
- struct servent *service=NULL;
- struct hostent *host=NULL;
- struct sockaddr_in r_addr;
- struct sockaddr_in sin;
- struct sockaddr_in l_addr;
- GSOCKNAME_T l_slen;
- #ifdef EXCELAN
- struct sockaddr_in send_socket;
- #endif /* EXCELAN */
- #ifdef INADDRX
- /* inet_addr() is of type struct in_addr */
- #ifdef datageneral
- extern struct in_addr inet_addr();
- #else
- #ifdef HPUX5WINTCP
- extern struct in_addr inet_addr();
- #endif /* HPUX5WINTCP */
- #endif /* datageneral */
- struct in_addr iax;
- #else
- #ifdef INADDR_NONE
- struct in_addr iax;
- #else /* INADDR_NONE */
- long iax;
- #endif /* INADDR_NONE */
- #endif /* INADDRX */
- if ( rdns_name == NULL || rdns_len < 0 )
- rdns_len = 0;
- *http_ip = '\0'; /* Initialize IP address string */
- namecopy[0] = '\0';
- #ifdef DEBUG
- if (deblog) {
- debug(F110,"http_open hostname",hostname,0);
- debug(F110,"http_open svcname",svcname,0);
- }
- #endif /* DEBUG */
- if (!hostname) hostname = "";
- if (!svcname) svcname = "";
- if (!*hostname || !*svcname) return(-1);
-
- service = ckgetservice(hostname,svcname,http_ip,20);
- if (service == NULL) {
- if ( !quiet )
- printf("?Invalid service: %s\r\n",svcname);
- return(-1);
- }
- /* For HTTP connections we must preserve the original hostname and */
- /* service requested so we can include them in the Host header. */
- ckmakmsg(http_host_port,sizeof(http_host_port),hostname,":",
- ckuitoa(ntohs(service->s_port)),NULL);
- http_port = ntohs(service->s_port);
- http_ssl = use_ssl;
- debug(F111,"http_open",http_host_port,http_port);
- /* 'http_ip' contains the IP address to which we want to connect */
- /* 'svcnam' contains the service name */
- /* 'service->s_port' contains the port number in network byte order */
- /* If we are using an http proxy, we need to create a buffer containing */
- /* hostname:port-number */
- /* to pass to the http_connect() function. Then we need to replace */
- /* 'namecopy' with the name of the proxy server and the service->s_port */
- /* with the port number of the proxy (default port 80). */
- if ( tcp_http_proxy ) {
- ckmakmsg(proxycopy,sizeof(proxycopy),hostname,":",
- ckuitoa(ntohs(service->s_port)),NULL);
- ckstrncpy(namecopy,tcp_http_proxy,NAMECPYL);
- p = namecopy; /* Was a service requested? */
- while (*p != '\0' && *p != ':') p++; /* Look for colon */
- if (*p == ':') { /* Have a colon */
- debug(F110,"http_open name has colon",namecopy,0);
- *p++ = '\0'; /* Get service name or number */
- } else {
- strcpy(++p,"http");
- }
- service = ckgetservice(namecopy,p,http_ip,20);
- if (!service) {
- fprintf(stderr, "Can't find port for service %s\n", p);
- #ifdef TGVORWIN
- debug(F101,"http_open can't get service for proxy","",socket_errno);
- #else
- debug(F101,"http_open can't get service for proxy","",errno);
- #endif /* TGVORWIN */
- errno = 0; /* (rather than mislead) */
- return(-1);
- }
- /* copy the proxyname and remove the service if any so we can use
- * it as the hostname
- */
- ckstrncpy(namecopy,tcp_http_proxy,NAMECPYL);
- p = namecopy; /* Was a service requested? */
- while (*p != '\0' && *p != ':') p++; /* Look for colon */
- if (*p == ':') { /* Have a colon */
- *p = '\0'; /* terminate string */
- }
- hostname = namecopy; /* use proxy as hostname */
- }
- /* Set up socket structure and get host address */
- bzero((char *)&r_addr, sizeof(r_addr));
- debug(F100,"http_open bzero ok","",0);
- #ifdef INADDR_NONE
- debug(F101,"http_open INADDR_NONE defined","",INADDR_NONE);
- #else /* INADDR_NONE */
- debug(F100,"http_open INADDR_NONE not defined","",0);
- #endif /* INADDR_NONE */
- #ifdef INADDRX
- debug(F100,"http_open INADDRX defined","",0);
- #else /* INADDRX */
- debug(F100,"http_open INADDRX not defined","",0);
- #endif /* INADDRX */
- #ifndef NOMHHOST
- #ifdef INADDRX
- iax = inet_addr(http_ip[0]?http_ip:hostname);
- debug(F111,"http_open inet_addr",http_ip[0]?http_ip:hostname,iax.s_addr);
- #else /* INADDRX */
- #ifdef INADDR_NONE
- iax.s_addr = inet_addr(http_ip[0]?http_ip:hostname);
- debug(F111,"http_open inet_addr",http_ip[0]?http_ip:hostname,iax.s_addr);
- #else /* INADDR_NONE */
- #ifndef datageneral
- iax = (unsigned int) inet_addr(http_ip[0]?http_ip:hostname);
- #else
- iax = -1L;
- #endif /* datageneral */
- debug(F111,"http_open inet_addr",http_ip[0]?http_ip:hostname,iax);
- #endif /* INADDR_NONE */
- #endif /* INADDRX */
- dns = 0;
- if (
- #ifdef INADDR_NONE
- /* This might give warnings on 64-bit platforms but they should be harmless */
- /* because INADDR_NONE should be all 1's anyway, thus the OR part is */
- /* probably superfluous -- not sure why it's even there, maybe it should be */
- /* removed. */
- iax.s_addr == INADDR_NONE /* || iax.s_addr == (unsigned long) -1L */
- #else /* INADDR_NONE */
- iax == -1
- #endif /* INADDR_NONE */
- ) {
- if (!quiet) {
- printf(" DNS Lookup... ");
- fflush(stdout);
- }
- if ((host = gethostbyname(http_ip[0] ? http_ip : hostname)) != NULL) {
- debug(F100,"http_open gethostbyname != NULL","",0);
- host = ck_copyhostent(host);
- dns = 1; /* Remember we performed dns lookup */
- r_addr.sin_family = host->h_addrtype;
- if (tcp_rdns && host->h_name && host->h_name[0] && (rdns_len > 0)
- && (tcp_http_proxy == NULL)
- )
- ckmakmsg(rdns_name,rdns_len,host->h_name,":",svcname,NULL);
- #ifdef HADDRLIST
- #ifdef h_addr
- /* This is for trying multiple IP addresses - see <netdb.h> */
- if (!(host->h_addr_list))
- return(-1);
- bcopy(host->h_addr_list[0],
- (caddr_t)&r_addr.sin_addr,
- host->h_length
- );
- #else
- bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
- #endif /* h_addr */
- #else /* HADDRLIST */
- bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
- #endif /* HADDRLIST */
- #ifdef COMMENT
- #ifndef EXCELAN
- debug(F111,"BCOPY","host->h_addr",host->h_addr);
- #endif /* EXCELAN */
- debug(F111,"BCOPY"," (caddr_t)&r_addr.sin_addr",
- (caddr_t)&r_addr.sin_addr);
- debug(F111,"BCOPY"," r_addr.sin_addr.s_addr",
- r_addr.sin_addr.s_addr);
- #endif /* COMMENT */
- debug(F111,"BCOPY","host->h_length",host->h_length);
- }
- }
- #endif /* NOMHHOST */
- if (!dns) {
- #ifdef INADDRX
- /* inet_addr() is of type struct in_addr */
- struct in_addr ina;
- unsigned long uu;
- debug(F100,"http_open gethostbyname == NULL: INADDRX","",0);
- ina = inet_addr(http_ip[0]?http_ip:hostname);
- uu = *(unsigned int *)&ina;
- #else /* Not INADDRX */
- /* inet_addr() is unsigned long */
- unsigned long uu;
- debug(F100,"http_open gethostbyname == NULL: Not INADDRX","",0);
- uu = inet_addr(http_ip[0]?http_ip:hostname);
- #endif /* INADDRX */
- debug(F101,"http_open uu","",uu);
- if (
- #ifdef INADDR_NONE
- !(uu == INADDR_NONE || uu == (unsigned int) -1L)
- #else /* INADDR_NONE */
- uu != ((unsigned long)-1)
- #endif /* INADDR_NONE */
- ) {
- r_addr.sin_addr.s_addr = uu;
- r_addr.sin_family = AF_INET;
- } else {
- #ifdef VMS
- fprintf(stdout, "\r\n"); /* complete any previous message */
- #endif /* VMS */
- fprintf(stderr, "Can't get address for %s\n",
- http_ip[0]?http_ip:hostname);
- #ifdef TGVORWIN
- debug(F101,"http_open can't get address","",socket_errno);
- #else
- debug(F101,"http_open can't get address","",errno);
- #endif /* TGVORWIN */
- errno = 0; /* Rather than mislead */
- return(-1);
- }
- }
- /* Get a file descriptor for the connection. */
- r_addr.sin_port = service->s_port;
- ckstrncpy(http_ip,(char *)inet_ntoa(r_addr.sin_addr),20);
- debug(F110,"http_open trying",http_ip,0);
- if (!quiet && *http_ip) {
- printf(" Trying %s... ", http_ip);
- fflush(stdout);
- }
- /* Loop to try additional IP addresses, if any. */
- do {
- #ifdef EXCELAN
- send_socket.sin_family = AF_INET;
- send_socket.sin_addr.s_addr = 0;
- send_socket.sin_port = 0;
- if ((httpfd = socket(SOCK_STREAM, (struct sockproto *)0,
- &send_socket, SO_REUSEADDR)) < 0)
- #else /* EXCELAN */
- if ((httpfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- #endif /* EXCELAN */
- {
- #ifdef EXCELAN
- experror("TCP socket error");
- #else
- #ifdef TGVORWIN
- #ifdef OLD_TWG
- errno = socket_errno;
- #endif /* OLD_TWG */
- socket_perror("TCP socket error");
- debug(F101,"http_open socket error","",socket_errno);
- #else
- perror("TCP socket error");
- debug(F101,"http_open socket error","",errno);
- #endif /* TGVORWIN */
- #endif /* EXCELAN */
- return (-1);
- }
- errno = 0;
- /* If a specific TCP address on the local host is desired we */
- /* must bind it to the socket. */
- #ifndef datageneral
- if (tcp_address) {
- int s_errno;
- debug(F110,"http_open binding socket to",tcp_address,0);
- bzero((char *)&sin,sizeof(sin));
- sin.sin_family = AF_INET;
- #ifdef INADDRX
- inaddrx = inet_addr(tcp_address);
- sin.sin_addr.s_addr = *(unsigned long *)&inaddrx;
- #else
- sin.sin_addr.s_addr = inet_addr(tcp_address);
- #endif /* INADDRX */
- sin.sin_port = 0;
- if (bind(httpfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- s_errno = socket_errno; /* Save error code */
- #ifdef TCPIPLIB
- socket_close(httpfd);
- #else /* TCPIPLIB */
- close(httpfd);
- #endif /* TCPIPLIB */
- httpfd = -1;
- errno = s_errno; /* and report this error */
- debug(F101,"http_open bind errno","",errno);
- return(-1);
- }
- }
- #endif /* datageneral */
- /* Now connect to the socket on the other end. */
- #ifdef EXCELAN
- if (connect(httpfd, &r_addr) < 0)
- #else
- #ifdef NT
- WSASafeToCancel = 1;
- #endif /* NT */
- if (connect(httpfd, (struct sockaddr *)&r_addr, sizeof(r_addr)) < 0)
- #endif /* EXCELAN */
- {
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- #ifdef OS2
- i = socket_errno;
- #else /* OS2 */
- #ifdef TGVORWIN
- i = socket_errno;
- #else
- i = errno; /* Save error code */
- #endif /* TGVORWIN */
- #endif /* OS2 */
- #ifdef HADDRLIST
- #ifdef h_addr
- if (host && host->h_addr_list && host->h_addr_list[1]) {
- perror("");
- host->h_addr_list++;
- bcopy(host->h_addr_list[0],
- (caddr_t)&r_addr.sin_addr,
- host->h_length);
- ckstrncpy(http_ip,(char *)inet_ntoa(r_addr.sin_addr),20);
- debug(F110,"http_open h_addr_list",http_ip,0);
- if (!quiet && *http_ip) {
- printf(" Trying %s... ", http_ip);
- fflush(stdout);
- }
- #ifdef TCPIPLIB
- socket_close(httpfd); /* Close it. */
- #else
- close(httpfd);
- #endif /* TCPIPLIB */
- continue;
- }
- #endif /* h_addr */
- #endif /* HADDRLIST */
- http_close();
- httpfd = -1;
- errno = i; /* And report this error */
- #ifdef EXCELAN
- if (errno) experror("http_open connect");
- #else
- #ifdef TGVORWIN
- debug(F101,"http_open connect error","",socket_errno);
- /* if (errno) socket_perror("http_open connect"); */
- #ifdef OLD_TWG
- errno = socket_errno;
- #endif /* OLD_TWG */
- if (!quiet)
- socket_perror("http_open connect");
- #else /* TGVORWIN */
- debug(F101,"http_open connect errno","",errno);
- #ifdef VMS
- if (!quiet)
- perror("\r\nFailed");
- #else
- if (!quiet)
- perror("Failed");
- #endif /* VMS */
- #ifdef DEC_TCPIP
- if (!quiet)
- perror("http_open connect");
- #endif /* DEC_TCPIP */
- #ifdef CMU_TCPIP
- if (!quiet)
- perror("http_open connect");
- #endif /* CMU_TCPIP */
- #endif /* TGVORWIN */
- #endif /* EXCELAN */
- return(-1);
- }
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- isconnect = 1;
- } while (!isconnect);
- #ifdef NON_BLOCK_IO
- on = 1;
- x = socket_ioctl(httpfd,FIONBIO,&on);
- debug(F101,"http_open FIONBIO","",x);
- #endif /* NON_BLOCK_IO */
- /* We have succeeded in connecting to the HTTP PROXY. So now we */
- /* need to attempt to connect through the proxy to the actual host */
- /* If that is successful, we have to pretend that we made a direct */
- /* connection to the actual host. */
- if ( tcp_http_proxy ) {
- #ifdef OS2
- if (!agent)
- agent = "Kermit 95"; /* Default user agent */
- #else
- if (!agent)
- agent = "C-Kermit";
- #endif /* OS2 */
- if (http_connect(httpfd,
- tcp_http_proxy_agent ? tcp_http_proxy_agent : agent,
- NULL,
- tcp_http_proxy_user,
- tcp_http_proxy_pwd,
- 0,
- proxycopy
- ) < 0) {
- http_close();
- return(-1);
- }
- }
- #ifdef SO_OOBINLINE
- /* See note on SO_OOBINLINE in netopen() */
- #ifdef datageneral
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef BSD43
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef OSF1
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef POSIX
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef MOTSV88R4
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef SOLARIS
- /*
- Maybe this applies to all SVR4 versions, but the other (else) way has been
- compiling and working fine on all the others, so best not to change it.
- */
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef OSK
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef OS2
- {
- int rc;
- rc = setsockopt(httpfd,
- SOL_SOCKET,
- SO_OOBINLINE,
- (char *) &on,
- sizeof on
- );
- debug(F111,"setsockopt SO_OOBINLINE",on ? "on" : "off" ,rc);
- }
- #else
- #ifdef VMS /* or, at least, VMS with gcc */
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- #ifdef CLIX
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
- #else
- setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
- #endif /* CLIX */
- #endif /* VMS */
- #endif /* OS2 */
- #endif /* OSK */
- #endif /* SOLARIS */
- #endif /* MOTSV88R4 */
- #endif /* POSIX */
- #endif /* BSD43 */
- #endif /* OSF1 */
- #endif /* datageneral */
- #endif /* SO_OOBINLINE */
- #ifndef NOTCPOPTS
- #ifndef datageneral
- #ifdef SOL_SOCKET
- #ifdef TCP_NODELAY
- no_delay(ttyfd,tcp_nodelay);
- #endif /* TCP_NODELAY */
- #ifdef SO_KEEPALIVE
- keepalive(ttyfd,tcp_keepalive);
- #endif /* SO_KEEPALIVE */
- #ifdef SO_LINGER
- ck_linger(ttyfd,tcp_linger, tcp_linger_tmo);
- #endif /* SO_LINGER */
- #ifdef SO_SNDBUF
- sendbuf(ttyfd,tcp_sendbuf);
- #endif /* SO_SNDBUF */
- #ifdef SO_RCVBUF
- recvbuf(ttyfd,tcp_recvbuf);
- #endif /* SO_RCVBUF */
- #endif /* SOL_SOCKET */
- #endif /* datageneral */
- #endif /* NOTCPOPTS */
- #ifndef datageneral
- /* Find out our own IP address. */
- /* We need the l_addr structure for [E]KLOGIN. */
- l_slen = sizeof(l_addr);
- bzero((char *)&l_addr, l_slen);
- #ifndef EXCELAN
- if (!getsockname(httpfd, (struct sockaddr *)&l_addr, &l_slen)) {
- char * s = (char *)inet_ntoa(l_addr.sin_addr);
- ckstrncpy(myipaddr, s, 20);
- debug(F110,"getsockname",myipaddr,0);
- }
- #endif /* EXCELAN */
- #endif /* datageneral */
- /* See note in netopen() on Reverse DNS lookups */
- if (tcp_rdns == SET_ON) {
- #ifdef NT
- if (isWin95())
- sleep(1);
- #endif /* NT */
- if (!quiet) {
- printf(" Reverse DNS Lookup... ");
- fflush(stdout);
- }
- if (host = gethostbyaddr((char *)&r_addr.sin_addr,4,PF_INET)) {
- char * s;
- host = ck_copyhostent(host);
- debug(F100,"http_open gethostbyname != NULL","",0);
- if (!quiet) {
- printf("(OK)\n");
- fflush(stdout);
- }
- s = host->h_name;
- if (!s) { /* This can happen... */
- debug(F100,"http_open host->h_name is NULL","",0);
- s = "";
- }
- /* Something is wrong with inet_ntoa() on HPUX 10.xx */
- /* The compiler says "Integral value implicitly converted to */
- /* pointer in assignment." The prototype is right there */
- /* in <arpa/inet.h> so what's the problem? */
- /* Ditto in HP-UX 5.x, but not 8.x or 9.x... */
- if (!*s) { /* No name so substitute the address */
- debug(F100,"http_open host->h_name is empty","",0);
- s = inet_ntoa(r_addr.sin_addr); /* Convert address to string */
- if (!s) /* Trust No 1 */
- s = "";
- if (*s) { /* If it worked, use this string */
- ckstrncpy(http_ip,s,20);
- }
- s = http_ip; /* Otherwise stick with the IP */
- if (!*s) /* or failing that */
- s = http_host_port; /* the name we were called with. */
- }
- if (*s) /* return the rdns name */
- ckmakmsg(rdns_name,rdns_len,s,":",svcname,NULL);
- if (!quiet && *s
- #ifndef NOICP
- && !doconx
- #endif /* NOICP */
- ) {
- printf(" %s connected on port %s\n",s,
- ckuitoa(ntohs(service->s_port)));
- #ifdef BETADEBUG
- /* This is simply for testing the DNS entries */
- if (host->h_aliases) {
- char ** a = host->h_aliases;
- while (*a) {
- printf(" alias => %s\n",*a);
- a++;
- }
- }
- #endif /* BETADEBUG */
- }
- } else {
- if (!quiet) printf("Failed.\n");
- }
- } else if (!quiet) printf("(OK)\n");
- if (!quiet) fflush(stdout);
- if ( tcp_http_proxy ) {
- /* Erase the IP address since we cannot reuse it */
- http_ip[0] = '\0';
- } else {
- /* This should already have been done but just in case */
- ckstrncpy(http_ip,(char *)inet_ntoa(r_addr.sin_addr),20);
- }
- makestr(&http_agent,agent);
- #ifdef CK_SSL
- if (use_ssl && ck_ssleay_is_installed()) {
- if (!ssl_http_init(hostname)) {
- if (bio_err!=NULL) {
- BIO_printf(bio_err,"ssl_tn_init() failed\n");
- ERR_print_errors(bio_err);
- } else {
- fflush(stderr);
- fprintf(stderr,"ssl_tn_init() failed\n");
- ERR_print_errors_fp(stderr);
- }
- http_close();
- return(-1);
- } else if ( ck_ssl_http_client(httpfd,hostname) < 0 ) {
- http_close();
- return(-1);
- }
- }
- #endif /* CK_SSL */
- #endif /* TCPSOCKET */
- return(0); /* Done. */
- }
- int
- #ifdef CK_ANSIC
- http_close(VOID)
- #else /* CK_ANSIC */
- http_close()
- #endif /* CK_ANSIC */
- {
- int x = 0;
- debug(F101,"http_close","",httpfd);
- #ifdef HTTP_BUFFERING
- http_count = 0;
- http_bufp = 0;
- #endif /* HTTP_BUFFERING */
- if (httpfd == -1) /* Was open? */
- return(0); /* Wasn't. */
- #ifndef OS2
- if (httpfd > -1) /* Was. */
- #endif /* OS2 */
- {
- #ifdef CK_SSL
- if (tls_http_active_flag) {
- if (ssl_debug_flag)
- BIO_printf(bio_err,"calling SSL_shutdown\n");
- SSL_shutdown(tls_http_con);
- tls_http_active_flag = 0;
- }
- #endif /* CK_SSL */
- #ifdef TCPIPLIB
- x = socket_close(httpfd); /* Close it. */
- #else
- #ifndef OS2
- x = close(httpfd);
- #endif /* OS2 */
- #endif /* TCPIPLIB */
- }
- httpfd = -1; /* Mark it as closed. */
- /* do not erase http_host_port, http_ip, http_port so they */
- /* can be used by http_reopen() */
- return(x);
- }
- /* http_tol()
- * Call with s = pointer to string, n = length.
- * Returns number of bytes actually written on success, or
- * -1 on i/o error, -2 if called improperly.
- */
- int
- http_tol(s,n) CHAR *s; int n; {
- int count = 0;
- int len = n;
- int try = 0;
- if (httpfd == -1) {
- debug(F100,"http_tol socket is closed","",0);
- return -1;
- }
- debug(F101,"http_tol TCPIPLIB ttnet","",ttnet);
- #ifdef COMMENT
- ckhexdump("http_tol",s,n);
- #endif /* COMMENT */
- #ifdef CK_SSL
- if (tls_http_active_flag) {
- int error, r;
- /* Write using SSL */
- ssl_retry:
- r = SSL_write(tls_http_con, s, len /* >1024?1024:len */);
- switch (SSL_get_error(tls_http_con,r)) {
- case SSL_ERROR_NONE:
- debug(F111,"http_tol","SSL_write",r);
- if ( r == len )
- return(n);
- s += r;
- len -= r;
- goto ssl_retry;
- case SSL_ERROR_WANT_WRITE:
- debug(F100,"http_tol SSL_ERROR_WANT_WRITE","",0);
- return(-1);
- case SSL_ERROR_WANT_READ:
- debug(F100,"http_tol SSL_ERROR_WANT_READ","",0);
- return(-1);
- case SSL_ERROR_SYSCALL:
- if ( r == 0 ) { /* EOF */
- http_close();
- return(-2);
- } else {
- int rc = -1;
- #ifdef NT
- int gle = GetLastError();
- debug(F111,"http_tol SSL_ERROR_SYSCALL",
- "GetLastError()",gle);
- rc = os2socketerror(gle);
- if (rc == -1)
- rc = -2;
- else if ( rc == -2 )
- return -1;
- #endif /* NT */
- return(rc);
- }
- case SSL_ERROR_WANT_X509_LOOKUP:
- debug(F100,"http_tol SSL_ERROR_WANT_X509_LOOKUP","",0);
- http_close();
- return(-2);
- case SSL_ERROR_SSL:
- debug(F100,"http_tol SSL_ERROR_SSL","",0);
- http_close();
- return(-2);
- case SSL_ERROR_ZERO_RETURN:
- debug(F100,"http_tol SSL_ERROR_ZERO_RETURN","",0);
- http_close();
- return(-2);
- default:
- debug(F100,"http_tol SSL_ERROR_?????","",0);
- http_close();
- return(-2);
- }
- }
- #endif /* CK_SSL */
- http_tol_retry:
- try++; /* Increase the try counter */
- {
- #ifdef BSDSELECT
- fd_set wfds;
- struct timeval tv;
- debug(F101,"http_tol BSDSELECT","",0);
- tv.tv_usec = 0L;
- tv.tv_sec=30;
- #ifdef NT
- WSASafeToCancel = 1;
- #endif /* NT */
- #ifdef STREAMING
- do_select:
- #endif /* STREAMING */
- FD_ZERO(&wfds);
- FD_SET(httpfd, &wfds);
- if (select(FD_SETSIZE, NULL,
- #ifdef __DECC
- #ifndef __DECC_VER
- (int *)
- #endif /* __DECC_VER */
- #endif /* __DECC */
- &wfds, NULL, &tv) < 0) {
- int s_errno = socket_errno;
- debug(F101,"http_tol select failed","",s_errno);
- #ifdef BETADEBUG
- printf("http_tol select failed: %d\n", s_errno);
- #endif /* BETADEBUG */
- #ifdef NT
- WSASafeToCancel = 0;
- if (!win95selectbug)
- #endif /* NT */
- return(-1);
- }
- if (!FD_ISSET(httpfd, &wfds)) {
- #ifdef STREAMING
- if (streaming)
- goto do_select;
- #endif /* STREAMING */
- debug(F111,"http_tol","!FD_ISSET",ttyfd);
- #ifdef NT
- WSASafeToCancel = 0;
- if (!win95selectbug)
- #endif /* NT */
- return(-1);
- }
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- #else /* BSDSELECT */
- #ifdef IBMSELECT
- {
- int tries = 0;
- debug(F101,"http_tol IBMSELECT","",0);
- while (select(&httpfd, 0, 1, 0, 1000) != 1) {
- int count;
- if (tries++ >= 60) {
- /* if after 60 seconds we can't get permission to write */
- debug(F101,"http_tol select failed","",socket_errno);
- return(-1);
- }
- #ifdef COMMENT
- if ((count = http_tchk()) < 0) {
- debug(F111,"http_tol","http_tchk()",count);
- return(count);
- }
- #endif /* COMMENT */
- }
- }
- #endif /* IBMSELECT */
- #endif /* BSDSELECT */
- #ifdef TCPIPLIB
- if ((count = socket_write(httpfd,s,n)) < 0) {
- int s_errno = socket_errno; /* maybe a function */
- debug(F101,"http_tol socket_write error","",s_errno);
- #ifdef OS2
- if (os2socketerror(s_errno) < 0)
- return(-2);
- #endif /* OS2 */
- return(-1); /* Call it an i/o error */
- }
- #else /* TCPIPLIB */
- if ((count = write(httpfd,s,n)) < 0) {
- debug(F101,"http_tol socket_write error","",errno);
- return(-1); /* Call it an i/o error */
- }
- #endif /* TCPIPLIB */
- if (count < n) {
- debug(F111,"http_tol socket_write",s,count);
- if (try > 25) {
- /* don't try more than 25 times */
- debug(F100,"http_tol tried more than 25 times","",0);
- return(-1);
- }
- if (count > 0) {
- s += count;
- n -= count;
- }
- debug(F111,"http_tol retry",s,n);
- goto http_tol_retry;
- } else {
- debug(F111,"http_tol socket_write",s,count);
- return(len); /* success - return total length */
- }
- }
- }
- int
- http_inc(timo) int timo; {
- int x=-1; unsigned char c; /* The locals. */
- if (httpfd == -1) {
- #ifdef HTTP_BUFFERING
- http_count = 0;
- http_bufp = 0;
- #endif /* HTTP_BUFFERING */
- debug(F100,"http_inc socket is closed","",0);
- return(-2);
- }
- #ifdef CK_SSL
- /*
- * In the case of OpenSSL, it is possible that there is still
- * data waiting in the SSL session buffers that has not yet
- * been read by Kermit. If this is the case we must process
- * it without calling select() because select() will not return
- * with an indication that there is data to be read from the
- * socket. If there is no data pending in the SSL session
- * buffers then fall through to the select() code and wait for
- * some data to arrive.
- */
- if (tls_http_active_flag) {
- int error;
- x = SSL_pending(tls_http_con);
- if (x < 0) {
- debug(F111,"http_inc","SSL_pending error",x);
- http_close();
- return(-1);
- } else if ( x > 0 ) {
- ssl_read:
- x = SSL_read(tls_http_con, &c, 1);
- error = SSL_get_error(tls_http_con,x);
- switch (error) {
- case SSL_ERROR_NONE:
- debug(F111,"http_inc SSL_ERROR_NONE","x",x);
- if (x > 0) {
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(c); /* Return character. */
- } else if (x < 0) {
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- } else {
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- case SSL_ERROR_WANT_WRITE:
- debug(F100,"http_inc SSL_ERROR_WANT_WRITE","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- case SSL_ERROR_WANT_READ:
- debug(F100,"http_inc SSL_ERROR_WANT_READ","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- case SSL_ERROR_SYSCALL:
- if ( x == 0 ) { /* EOF */
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- } else {
- int rc = -1;
- #ifdef NT
- int gle = GetLastError();
- debug(F111,"http_inc SSL_ERROR_SYSCALL",
- "GetLastError()",gle);
- rc = os2socketerror(gle);
- if (rc == -1)
- rc = -2;
- else if ( rc == -2 )
- rc = -1;
- #endif /* NT */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(rc);
- }
- case SSL_ERROR_WANT_X509_LOOKUP:
- debug(F100,"http_inc SSL_ERROR_WANT_X509_LOOKUP","",0);
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- case SSL_ERROR_SSL:
- debug(F100,"http_inc SSL_ERROR_SSL","",0);
- #ifdef COMMENT
- http_close();
- #endif /* COMMENT */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- case SSL_ERROR_ZERO_RETURN:
- debug(F100,"http_inc SSL_ERROR_ZERO_RETURN","",0);
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- default:
- debug(F100,"http_inc SSL_ERROR_?????","",0);
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- }
- }
- #endif /* CK_SSL */
- #ifdef HTTP_BUFFERING
- /* Skip all the select() stuff if we have bytes buffered locally */
- if (http_count > 0)
- goto getfrombuffer;
- #endif /* HTTP_BUFFERING */
- {
- #ifdef BSDSELECT
- fd_set rfds;
- struct timeval tv;
- int timeout = timo < 0 ? -timo : 1000 * timo;
- debug(F101,"http_inc BSDSELECT","",timo);
- for ( ; timeout >= 0; timeout -= (timo ? 100 : 0)) {
- int rc;
- debug(F111,"http_inc","timeout",timeout);
- /* Don't move select() initialization out of the loop. */
- FD_ZERO(&rfds);
- FD_SET(httpfd, &rfds);
- tv.tv_sec = tv.tv_usec = 0L;
- if (timo)
- tv.tv_usec = (long) 100000L;
- else
- tv.tv_sec = 30;
- #ifdef NT
- WSASafeToCancel = 1;
- #endif /* NT */
- rc = select(FD_SETSIZE,
- #ifndef __DECC
- (fd_set *)
- #endif /* __DECC */
- &rfds, NULL, NULL, &tv);
- if (rc < 0) {
- int s_errno = socket_errno;
- debug(F111,"http_inc","select",rc);
- debug(F111,"http_inc","socket_errno",s_errno);
- #ifdef HTTP_BUFFERING
- http_count = 0;
- http_bufp = 0;
- #endif /* HTTP_BUFFERING */
- if (s_errno)
- return(-1);
- }
- debug(F111,"http_inc","select",rc);
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- if (FD_ISSET(httpfd, &rfds)) {
- x = 0;
- break;
- } else {
- /* If waiting forever we have no way of knowing if the */
- /* socket closed so try writing a 0-length TCP packet */
- /* which should force an error if the socket is closed */
- if (!timo) {
- #ifdef TCPIPLIB
- if ((rc = socket_write(httpfd,"",0)) < 0) {
- #ifdef HTTP_BUFFERING
- http_count = 0;
- http_bufp = 0;
- #endif /* HTTP_BUFFERING */
- int s_errno = socket_errno;
- debug(F101,"http_inc socket_write error","",s_errno);
- #ifdef OS2
- if (os2socketerror(s_errno) < 0)
- return(-2);
- #endif /* OS2 */
- return(-1); /* Call it an i/o error */
- }
- #else /* TCPIPLIB */
- if ((rc = write(httpfd,"",0)) < 0) {
- #ifdef HTTP_BUFFERING
- http_count = 0;
- http_bufp = 0;
- #endif /* HTTP_BUFFERING */
- debug(F101,"http_inc socket_write error","",errno);
- return(-1); /* Call it an i/o error */
- }
- #endif /* TCPIPLIB */
- }
- continue;
- }
- }
- #ifdef NT
- WSASafeToCancel = 0;
- #endif /* NT */
- #else /* !BSDSELECT */
- #ifdef IBMSELECT
- /*
- Was used by OS/2, currently not used, but might come in handy some day...
- ... and it came in handy! For our TCP/IP layer, it avoids all the fd_set
- and timeval stuff since this is the only place where it is used.
- */
- int socket = httpfd;
- int timeout = timo < 0 ? -timo : 1000 * timo;
- debug(F101,"http_inc IBMSELECT","",timo);
- for ( ; timeout >= 0; timeout -= (timo ? 100 : 0)) {
- if (select(&socket, 1, 0, 0, 100L) == 1) {
- x = 0;
- break;
- }
- }
- #else /* !IBMSELECT */
- SELECT is required for this code
- #endif /* IBMSELECT */
- #endif /* BSDSELECT */
- }
- if (timo && x < 0) { /* select() timed out */
- #ifdef HTTP_BUFFERING
- http_count = 0;
- http_bufp = 0;
- #endif /* HTTP_BUFFERING */
- debug(F100,"http_inc select() timed out","",0);
- return(-1); /* Call it an i/o error */
- }
- #ifdef CK_SSL
- if ( tls_http_active_flag ) {
- int error;
- ssl_read2:
- x = SSL_read(tls_http_con, &c, 1);
- error = SSL_get_error(tls_http_con,x);
- switch (error) {
- case SSL_ERROR_NONE:
- debug(F111,"http_inc SSL_ERROR_NONE","x",x);
- if (x > 0) {
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(c); /* Return character. */
- } else if (x < 0) {
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- } else {
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- case SSL_ERROR_WANT_WRITE:
- debug(F100,"http_inc SSL_ERROR_WANT_WRITE","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- case SSL_ERROR_WANT_READ:
- debug(F100,"http_inc SSL_ERROR_WANT_READ","",0);
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-1);
- case SSL_ERROR_SYSCALL:
- if ( x == 0 ) { /* EOF */
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- } else {
- int rc = -1;
- #ifdef NT
- int gle = GetLastError();
- debug(F111,"http_inc SSL_ERROR_SYSCALL",
- "GetLastError()",gle);
- rc = os2socketerror(gle);
- if (rc == -1)
- rc = -2;
- else if ( rc == -2 )
- rc = -1;
- #endif /* NT */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(rc);
- }
- case SSL_ERROR_WANT_X509_LOOKUP:
- debug(F100,"http_inc SSL_ERROR_WANT_X509_LOOKUP","",0);
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- case SSL_ERROR_SSL:
- debug(F100,"http_inc SSL_ERROR_SSL","",0);
- #ifdef COMMENT
- http_close();
- #endif /* COMMENT */
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- case SSL_ERROR_ZERO_RETURN:
- debug(F100,"http_inc SSL_ERROR_ZERO_RETURN","",0);
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- default:
- debug(F100,"http_inc SSL_ERROR_?????","",0);
- http_close();
- #ifdef OS2
- ReleaseTCPIPMutex();
- #endif /* OS2 */
- return(-2);
- }
- }
- #endif /* CK_SSL */
- #ifdef HTTP_BUFFERING
- /*
- Buffering code added by fdc 15 Dec 2005 for non-SSL case only because HTTP
- GETs were orders of magnitude too slow due to the single-byte read()s. The
- file-descriptor swapping is pretty gross, but the more elegant solution
- (calling a nettchk() like routine with the fd as a parameter) doesn't work,
- because nettchk() relies on too many other routines that, like itself, are
- hardwired for ttyfd.
- */
- getfrombuffer:
- if (--http_count >= 0) {
- c = http_inbuf[http_bufp++];
- x = 1;
- } else {
- int savefd;
- savefd = ttyfd;
- ttyfd = httpfd;
- x = nettchk();
- ttyfd = savefd;
- debug(F101,"http_inc nettchk","",x);
- if (x > HTTP_INBUFLEN)
- x = HTTP_INBUFLEN;
- #ifdef TCPIPLIB
- x = socket_read(httpfd,http_inbuf,x);
- #else /* Not TCPIPLIB */
- x = read(httpfd,http_inbuf,x);
- #endif /* TCPIPLIB */
- http_count = 0;
- http_bufp = 0;
- if (x > 0) {
- c = http_inbuf[http_bufp++];
- http_count = x - 1;
- }
- }
- #else /* Not HTTP_BUFFERING */
- #ifdef TCPIPLIB
- x = socket_read(httpfd,&c,1);
- #else /* Not TCPIPLIB */
- x = read(httpfd,&c,1);
- #endif /* TCPIPLIB */
- #endif /* HTTP_BUFFERING */
- if (x <= 0) {
- int s_errno = socket_errno;
- debug(F101,"ttbufr socket_read","",x);
- debug(F101,"ttbufr socket_errno","",s_errno);
- #ifdef OS2
- if (x == 0 || os2socketerror(s_errno) < 0) {
- http_close();
- ReleaseTCPIPMutex();
- return(-2);
- }
- ReleaseTCPIPMutex();
- return(-1);
- #else /* OS2 */
- http_close(); /* *** *** */
- return(-2);
- #endif /* OS2 */
- }
- return(c);
- }
- void
- #ifdef CK_ANSIC
- http_set_code_reply(char * msg)
- #else
- http_set_code_reply(msg)
- char * msg;
- #endif /* CK_ANSIC */
- {
- char * p = msg;
- char buf[16];
- int i=0;
- while ( *p != SP && *p != NUL ) {
- buf[i] = *p;
- p++;
- i++;
- }
- http_code = atoi(buf);
- while ( *p == SP )
- p++;
- ckstrncpy(http_reply_str,p,HTTPBUFLEN);
- }
- int
- #ifdef CK_ANSIC
- http_get(char * agent, char ** hdrlist, char * user,
- char * pwd, char array, char * local, char * remote,
- int stdio)
- #else
- http_get(agent, hdrlist, user, pwd, array, local, remote, stdio)
- char * agent; char ** hdrlist; char * user;
- char * pwd; char array; char * local; char * remote;
- int stdio;
- #endif /* CK_ANSIC */
- {
- char * request = NULL;
- int i, j, len = 0, hdcnt = 0, rc = 0;
- int ch;
- int http_fnd = 0;
- char buf[HTTPBUFLEN], *p;
- int nullline;
- #ifdef OS2
- struct utimbuf u_t;
- #else /* OS2 */
- #ifdef SYSUTIMEH
- struct utimbuf u_t;
- #else
- struct utimbuf {
- time_t atime;
- time_t mtime;
- } u_t;
- #endif /* SYSUTIMH */
- #endif /* OS2 */
- time_t mod_t = 0;
- time_t srv_t = 0;
- time_t local_t = 0;
- char passwd[64];
- char b64in[128];
- char b64out[256];
- char * headers[HTTPHEADCNT];
- int closecon = 0;
- int chunked = 0;
- int zfile = 0;
- int first = 1;
- #ifdef DEBUG
- if (deblog) {
- debug(F101,"http_get httpfd","",httpfd);
- debug(F110,"http_agent",agent,0);
- debug(F110,"http_user",user,0);
- debug(F110,"http_local",local,0);
- debug(F110,"http_remote",remote,0);
- }
- #endif /* DEBUG */
- if (!remote) remote = "";
- if (httpfd == -1)
- return(-1);
- if (array) {
- for (i = 0; i < HTTPHEADCNT; i++)
- headers[i] = NULL;
- }
- len = 8; /* GET */
- len += strlen(HTTP_VERSION);
- len += strlen(remote);
- len += 16;
- if (hdrlist) {
- for (i = 0; hdrlist[i]; i++)
- len += strlen(hdrlist[i]) + 2;
- }
- len += (int) strlen(http_host_port) + 8;
- if (agent)
- len += 13 + strlen(agent);
- if (user) {
- if (!pwd) {
- readpass("Password: ",passwd,64);
- pwd = passwd;
- }
- ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
- j = b8tob64(b64in,strlen(b64in),b64out,256);
- memset(pwd,0,strlen(pwd)); /* NOT PORTABLE */
- if (j < 0)
- return(-1);
- b64out[j] = '\0';
- len += j + 24;
- }
- #ifdef HTTP_CLOSE
- len += 19; /* Connection: close */
- #endif
- len += 3; /* blank line + null */
- request = malloc(len);
- if (!request)
- return(-1);
- sprintf(request,"GET %s %s\r\n",remote,HTTP_VERSION); /* safe */
- ckstrncat(request,"Host: ", len);
- ckstrncat(request,http_host_port, len);
- ckstrncat(request,"\r\n",len);
- if (agent) {
- ckstrncat(request,"User-agent: ",len);
- ckstrncat(request,agent,len);
- ckstrncat(request,"\r\n",len);
- }
- if (user) {
- ckstrncat(request,"Authorization: Basic ",len);
- ckstrncat(request,b64out,len);
- ckstrncat(request,"\r\n",len);
- }
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++) {
- ckstrncat(request,hdrlist[i],len);
- ckstrncat(request,"\r\n",len);
- }
- }
- #ifdef HTTP_CLOSE
- ckstrncat(request,"Connection: close\r\n",len);
- #endif
- ckstrncat(request,"\r\n",len);
- getreq:
- if (http_tol((CHAR *)request,strlen(request)) < 0)
- {
- http_close();
- if ( first ) {
- first--;
- http_reopen();
- goto getreq;
- }
- rc = -1;
- goto getexit;
- }
- /* Process the headers */
- local_t = time(NULL);
- nullline = 0;
- i = 0;
- len = -1;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if ( buf[i] == 10 ) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"HTTP",4,0)) {
- http_fnd = 1;
- j = ckindex(" ",buf,0,0,0);
- p = &buf[j];
- while ( isspace(*p) )
- p++;
- switch ( p[0] ) {
- case '1': /* Informational message */
- break;
- case '2': /* Success */
- break;
- case '3': /* Redirection */
- case '4': /* Client failure */
- case '5': /* Server failure */
- default: /* Unknown */
- if (!quiet)
- printf("Failure: Server reports %s\n",p);
- rc = -1;
- local = NULL;
- }
- http_set_code_reply(p);
- #ifdef CMDATE2TM
- } else if (!ckstrcmp(buf,"Last-Modified",13,0)) {
- mod_t = http_date(&buf[15]);
- } else if (!ckstrcmp(buf,"Date",4,0)) {
- srv_t = http_date(&buf[4]);
- #endif /* CMDATE2TM */
- } else if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
- len = atoi(&buf[16]);
- } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
- if ( ckindex("chunked",buf,18,0,0) != 0 )
- chunked = 1;
- debug(F101,"http_get chunked","",chunked);
- }
- i = 0;
- } else {
- i++;
- }
- }
- if (ch < 0 && first) {
- first--;
- http_close();
- http_reopen();
- goto getreq;
- }
- if (http_fnd == 0) {
- rc = -1;
- closecon = 1;
- goto getexit;
- }
- /* Now we have the contents of the file */
- if ( local && local[0] ) {
- if (zopeno(ZOFILE,local,NULL,NULL))
- zfile = 1;
- else
- rc = -1;
- }
- if ( chunked ) {
- while ((len = http_get_chunk_len()) > 0) {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- if ( zfile )
- zchout(ZOFILE,(CHAR)ch);
- if ( stdio )
- conoc((CHAR)ch);
- }
- if ((ch = http_inc(0)) != CR)
- break;
- if ((ch = http_inc(0)) != LF)
- break;
- }
- } else {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- if ( zfile )
- zchout(ZOFILE,(CHAR)ch);
- if ( stdio )
- conoc((CHAR)ch);
- }
- }
- if ( zfile )
- zclose(ZOFILE);
- if ( chunked ) { /* Parse Trailing Headers */
- nullline = 0;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if ( buf[i] == 10 ) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- #ifdef CMDATE2TM
- if (!ckstrcmp(buf,"Last-Modified",13,0)) {
- mod_t = http_date(&buf[15]);
- } else if (!ckstrcmp(buf,"Date",4,0)) {
- srv_t = http_date(&buf[4]);
- }
- #endif /* CMDATE2TM */
- else if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- }
- i = 0;
- } else {
- i++;
- }
- }
- }
- if ( zfile ) { /* Set timestamp */
- #ifndef NOSETTIME
- #ifdef OS2
- u_t.actime = srv_t ? srv_t : local_t;
- u_t.modtime = mod_t ? mod_t : local_t;
- #else /* OS2 */
- #ifdef SYSUTIMEH
- u_t.actime = srv_t ? srv_t : local_t;
- u_t.modtime = mod_t ? mod_t : local_t;
- #else
- #ifdef BSD44
- u_t[0].tv_sec = srv_t ? srv_t : local_t;
- u_t[1].tv_sec = mod_t ? mod_t : local_t;
- #else
- u_t.mtime = srv_t ? srv_t : local_t;
- u_t.atime = mod_t ? mod_t : local_t;
- #endif /* BSD44 */
- #endif /* SYSUTIMEH */
- #endif /* OS2 */
- utime(local,&u_t);
- #endif /* NOSETTIME */
- }
- getexit:
- if (array)
- http_mkarray(headers,hdcnt,array);
- if ( closecon )
- http_close();
- free(request);
- for (i = 0; i < hdcnt; i++) {
- if (headers[i])
- free(headers[i]);
- }
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- http_head(char * agent, char ** hdrlist, char * user,
- char * pwd, char array, char * local, char * remote,
- int stdio)
- #else
- http_head(agent, hdrlist, user, pwd, array, local, remote, stdio)
- char * agent; char ** hdrlist; char * user;
- char * pwd; char array; char * local; char * remote;
- int stdio;
- #endif /* CK_ANSIC */
- {
- char * request = NULL;
- int i, j, len = 0, hdcnt = 0, rc = 0;
- int ch;
- int http_fnd = 0;
- char buf[HTTPBUFLEN], *p;
- int nullline;
- time_t mod_t;
- time_t srv_t;
- time_t local_t;
- char passwd[64];
- char b64in[128];
- char b64out[256];
- char * headers[HTTPHEADCNT];
- int closecon = 0;
- int first = 1;
- if (httpfd == -1)
- return(-1);
- if (array) {
- for (i = 0; i < HTTPHEADCNT; i++)
- headers[i] = NULL;
- }
- len = 9; /* HEAD */
- len += strlen(HTTP_VERSION);
- len += strlen(remote);
- len += 16;
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++)
- len += strlen(hdrlist[i]) + 2;
- }
- len += strlen(http_host_port) + 8;
- if (agent)
- len += 13 + strlen(agent);
- if (user) {
- if (!pwd) {
- readpass("Password: ",passwd,64);
- pwd = passwd;
- }
- ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
- j = b8tob64(b64in,strlen(b64in),b64out,256);
- memset(pwd,0,strlen(pwd)); /* NOT PORTABLE */
- if (j < 0)
- return(-1);
- b64out[j] = '\0';
- len += j + 24;
- }
- #ifdef HTTP_CLOSE
- len += 19; /* Connection: close */
- #endif
- len += 3; /* blank line + null */
- request = (char *)malloc(len);
- if (!request)
- return(-1);
- sprintf(request,"HEAD %s %s\r\n",remote,HTTP_VERSION);
- ckstrncat(request,"Host: ", len);
- ckstrncat(request,http_host_port, len);
- ckstrncat(request,"\r\n",len);
- if (agent) {
- ckstrncat(request,"User-agent: ",len);
- ckstrncat(request,agent,len);
- ckstrncat(request,"\r\n",len);
- }
- if (user) {
- ckstrncat(request,"Authorization: Basic ",len);
- ckstrncat(request,b64out,len);
- ckstrncat(request,"\r\n",len);
- }
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++) {
- ckstrncat(request,hdrlist[i],len);
- ckstrncat(request,"\r\n",len);
- }
- }
- #ifdef HTTP_CLOSE
- ckstrncat(request,"Connection: close\r\n",len);
- #endif
- ckstrncat(request,"\r\n",len);
- if ( local && local[0] ) {
- if (!zopeno(ZOFILE,local,NULL,NULL)) {
- free(request);
- return(-1);
- }
- }
- headreq:
- if (http_tol((CHAR *)request,strlen(request)) < 0)
- {
- http_close();
- if ( first ) {
- first--;
- http_reopen();
- goto headreq;
- }
- rc = -1;
- goto headexit;
- }
- /* Process the headers */
- local_t = time(NULL);
- nullline = 0;
- i = 0;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if (buf[i] == 10) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"HTTP",4,0)) {
- http_fnd = 1;
- j = ckindex(" ",buf,0,0,0);
- p = &buf[j];
- while (isspace(*p))
- p++;
- switch (p[0]) {
- case '1': /* Informational message */
- break;
- case '2': /* Success */
- break;
- case '3': /* Redirection */
- case '4': /* Client failure */
- case '5': /* Server failure */
- default: /* Unknown */
- if (!quiet)
- printf("Failure: Server reports %s\n",p);
- rc = -1;
- }
- http_set_code_reply(p);
- } else {
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- }
- if ( local && local[0] ) {
- zsout(ZOFILE,buf);
- zsout(ZOFILE,"\r\n");
- }
- if (stdio)
- printf("%s\r\n",buf);
- }
- i = 0;
- } else {
- i++;
- }
- }
- if (ch < 0 && first) {
- first--;
- http_close();
- http_reopen();
- goto headreq;
- }
- if ( http_fnd == 0 )
- rc = -1;
- if (array)
- http_mkarray(headers,hdcnt,array);
- headexit:
- if ( local && local[0] )
- zclose(ZOFILE);
- if (closecon)
- http_close();
- free(request);
- for (i = 0; i < hdcnt; i++) {
- if (headers[i])
- free(headers[i]);
- }
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- http_index(char * agent, char ** hdrlist, char * user, char * pwd,
- char array, char * local, char * remote, int stdio)
- #else
- http_index(agent, hdrlist, user, pwd, array, local, remote, stdio)
- char * agent; char ** hdrlist; char * user; char * pwd;
- char array; char * local; char * remote; int stdio;
- #endif /* CK_ANSIC */
- {
- char * request = NULL;
- int i, j, len = 0, hdcnt = 0, rc = 0;
- int ch;
- int http_fnd = 0;
- char buf[HTTPBUFLEN], *p;
- int nullline;
- time_t mod_t;
- time_t srv_t;
- time_t local_t;
- char passwd[64];
- char b64in[128];
- char b64out[256];
- char * headers[HTTPHEADCNT];
- int closecon = 0;
- int chunked = 0;
- int zfile = 0;
- int first = 1;
- if (httpfd == -1)
- return(-1);
- if (array) {
- for (i = 0; i < HTTPHEADCNT; i++)
- headers[i] = NULL;
- }
- len = 10; /* INDEX */
- len += strlen(HTTP_VERSION);
- len += strlen(remote);
- len += 16;
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++)
- len += strlen(hdrlist[i]) + 2;
- }
- len += strlen(http_host_port) + 8;
- if (agent)
- len += 13 + strlen(agent);
- if (user) {
- if (!pwd) {
- readpass("Password: ",passwd,64);
- pwd = passwd;
- }
- ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
- j = b8tob64(b64in,strlen(b64in),b64out,256);
- memset(pwd,0,strlen(pwd));
- if (j < 0)
- return(-1);
- b64out[j] = '\0';
- len += j + 24;
- }
- #ifdef HTTP_CLOSE
- len += 19; /* Connection: close */
- #endif
- len += 3; /* blank line + null */
- request = malloc(len);
- if (!request)
- return(-1);
- sprintf(request,"INDEX %s\r\n",HTTP_VERSION);
- ckstrncat(request,"Host: ", len);
- ckstrncat(request,http_host_port, len);
- ckstrncat(request,"\r\n",len);
- if (agent) {
- ckstrncat(request,"User-agent: ",len);
- ckstrncat(request,agent,len);
- ckstrncat(request,"\r\n",len);
- }
- if (user) {
- ckstrncat(request,"Authorization: Basic ",len);
- ckstrncat(request,b64out,len);
- ckstrncat(request,"\r\n",len);
- }
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++) {
- ckstrncat(request,hdrlist[i],len);
- ckstrncat(request,"\r\n",len);
- }
- }
- #ifdef HTTP_CLOSE
- ckstrncat(request,"Connection: close\r\n",len);
- #endif
- ckstrncat(request,"\r\n",len);
- indexreq:
- if (http_tol((CHAR *)request,strlen(request)) < 0)
- {
- http_close();
- if ( first ) {
- first--;
- http_reopen();
- goto indexreq;
- }
- rc = -1;
- goto indexexit;
- }
- /* Process the headers */
- local_t = time(NULL);
- nullline = 0;
- i = 0;
- len = -1;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if (buf[i] == 10) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"HTTP",4,0)) {
- http_fnd = 1;
- j = ckindex(" ",buf,0,0,0);
- p = &buf[j];
- while (isspace(*p))
- p++;
- switch ( p[0] ) {
- case '1': /* Informational message */
- break;
- case '2': /* Success */
- break;
- case '3': /* Redirection */
- case '4': /* Client failure */
- case '5': /* Server failure */
- default: /* Unknown */
- if (!quiet)
- printf("Failure: Server reports %s\n",p);
- rc = -1;
- }
- http_set_code_reply(p);
- } else if ( !nullline ) {
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
- len = atoi(&buf[16]);
- } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
- if ( ckindex("chunked",buf,18,0,0) != 0 )
- chunked = 1;
- debug(F101,"http_index chunked","",chunked);
- }
- printf("%s\n",buf);
- }
- i = 0;
- } else {
- i++;
- }
- }
- if (ch < 0 && first) {
- first--;
- http_close();
- http_reopen();
- goto indexreq;
- }
- if ( http_fnd == 0 ) {
- rc = -1;
- closecon = 1;
- goto indexexit;
- }
- /* Now we have the contents of the file */
- if ( local && local[0] ) {
- if (zopeno(ZOFILE,local,NULL,NULL))
- zfile = 1;
- else
- rc = -1;
- }
- if ( chunked ) {
- while ((len = http_get_chunk_len()) > 0) {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- if ( zfile )
- zchout(ZOFILE,(CHAR)ch);
- if ( stdio )
- conoc((CHAR)ch);
- }
- if ((ch = http_inc(0)) != CR)
- break;
- if ((ch = http_inc(0)) != LF)
- break;
- }
- } else {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- if ( zfile )
- zchout(ZOFILE,(CHAR)ch);
- if ( stdio )
- conoc((CHAR)ch);
- }
- }
- if ( zfile )
- zclose(ZOFILE);
- if ( chunked ) { /* Parse Trailing Headers */
- nullline = 0;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if ( buf[i] == 10 ) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- }
- i = 0;
- } else {
- i++;
- }
- }
- }
- rc = 0;
- indexexit:
- if (array)
- http_mkarray(headers,hdcnt,array);
- if (closecon)
- http_close();
- free(request);
- for (i = 0; i < hdcnt; i++) {
- if (headers[i])
- free(headers[i]);
- }
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- http_put(char * agent, char ** hdrlist, char * mime, char * user,
- char * pwd, char array, char * local, char * remote,
- char * dest, int stdio)
- #else
- http_put(agent, hdrlist, mime, user, pwd, array, local, remote, dest, stdio)
- char * agent; char ** hdrlist; char * mime; char * user;
- char * pwd; char array; char * local; char * remote; char * dest;
- int stdio;
- #endif /* CK_ANSIC */
- {
- char * request=NULL;
- int i, j, len = 0, hdcnt = 0, rc = 0;
- int ch;
- int http_fnd = 0;
- char buf[HTTPBUFLEN], *p;
- int nullline;
- time_t mod_t;
- time_t srv_t;
- time_t local_t;
- char passwd[64];
- char b64in[128];
- char b64out[256];
- int filelen;
- char * headers[HTTPHEADCNT];
- int closecon = 0;
- int chunked = 0;
- int first = 1;
- int zfile = 0;
- if (httpfd == -1)
- return(-1);
- if (!mime) mime = "";
- if (!remote) remote = "";
- if (!local) local = "";
- if (!*local) return(-1);
- if (array) {
- for (i = 0; i < HTTPHEADCNT; i++)
- headers[i] = NULL;
- }
- filelen = zchki(local);
- if (filelen < 0)
- return(-1);
- /* Compute length of request header */
- len = 8; /* PUT */
- len += strlen(HTTP_VERSION);
- len += strlen(remote);
- len += 16;
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++)
- len += strlen(hdrlist[i]) + 2;
- }
- len += strlen(http_host_port) + 8;
- if (agent)
- len += 13 + strlen(agent);
- if (user) {
- if (!pwd) {
- readpass("Password: ",passwd,64);
- pwd = passwd;
- }
- ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
- j = b8tob64(b64in,strlen(b64in),b64out,256);
- memset(pwd,0,strlen(pwd));
- if (j < 0)
- return(-1);
- b64out[j] = '\0';
- len += j + 24;
- }
- len += 16 + strlen(mime); /* Content-type: */
- len += 32; /* Content-length: */
- len += 32; /* Date: */
- #ifdef HTTP_CLOSE
- len += 19; /* Connection: close */
- #endif
- len += 3; /* blank line + null */
- request = malloc(len);
- if (!request)
- return(-1);
- sprintf(request,"PUT %s %s\r\n",remote,HTTP_VERSION);
- ckstrncat(request,"Date: ",len);
- #ifdef CMDATE2TM
- ckstrncat(request,http_now(),len);
- #else
- ckstrncat(request,...,len);
- #endif /* CMDATE2TM */
- ckstrncat(request,"\r\n",len);
- ckstrncat(request,"Host: ", len);
- ckstrncat(request,http_host_port, len);
- ckstrncat(request,"\r\n",len);
- if (agent) {
- ckstrncat(request,"User-agent: ",len);
- ckstrncat(request,agent,len);
- ckstrncat(request,"\r\n",len);
- }
- if (user) {
- ckstrncat(request,"Authorization: Basic ",len);
- ckstrncat(request,b64out,len);
- ckstrncat(request,"\r\n",len);
- }
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++) {
- ckstrncat(request,hdrlist[i],len);
- ckstrncat(request,"\r\n",len);
- }
- }
- ckstrncat(request,"Content-type: ",len);
- ckstrncat(request,mime,len);
- ckstrncat(request,"\r\n",len);
- sprintf(buf,"Content-length: %d\r\n",filelen); /* safe */
- ckstrncat(request,buf,len);
- #ifdef HTTP_CLOSE
- ckstrncat(request,"Connection: close\r\n",len);
- #endif
- ckstrncat(request,"\r\n",len);
- /* Now we have the contents of the file */
- if (zopeni(ZIFILE,local)) {
- putreq: /* Send request */
- if (http_tol((CHAR *)request,strlen(request)) <= 0) {
- http_close();
- if ( first ) {
- first--;
- http_reopen();
- goto putreq;
- }
- zclose(ZIFILE);
- rc = -1;
- goto putexit;
- }
- /* Request headers have been sent */
- i = 0;
- while (zchin(ZIFILE,&ch) == 0) {
- buf[i++] = ch;
- if (i == HTTPBUFLEN) {
- if (http_tol((CHAR *)buf,HTTPBUFLEN) <= 0) {
- http_close();
- if ( first ) {
- first--;
- http_reopen();
- goto putreq;
- }
- }
- i = 0;
- }
- }
- if (i > 0) {
- if (http_tol((CHAR *)buf,i) < 0) {
- http_close();
- if ( first ) {
- first--;
- http_reopen();
- goto putreq;
- }
- }
- }
- zclose(ZIFILE);
- /* Process the response headers */
- local_t = time(NULL);
- nullline = 0;
- i = 0;
- len = -1;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if (buf[i] == 10) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"HTTP",4,0)) {
- http_fnd = 1;
- j = ckindex(" ",buf,0,0,0);
- p = &buf[j];
- while (isspace(*p))
- p++;
- switch (p[0]) {
- case '1': /* Informational message */
- break;
- case '2': /* Success */
- break;
- case '3': /* Redirection */
- case '4': /* Client failure */
- case '5': /* Server failure */
- default: /* Unknown */
- if (!quiet)
- printf("Failure: Server reports %s\n",p);
- rc = -1;
- }
- http_set_code_reply(p);
- } else {
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
- len = atoi(&buf[16]);
- } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
- if ( ckindex("chunked",buf,18,0,0) != 0 )
- chunked = 1;
- debug(F101,"http_put chunked","",chunked);
- }
- if ( stdio )
- printf("%s\n",buf);
- }
- i = 0;
- } else {
- i++;
- }
- }
- if (ch < 0 && first) {
- first--;
- http_close();
- http_reopen();
- goto putreq;
- }
- if ( http_fnd == 0 ) {
- closecon = 1;
- rc = -1;
- goto putexit;
- }
- /* Any response data? */
- if ( dest && dest[0] ) {
- if (zopeno(ZOFILE,dest,NULL,NULL))
- zfile = 1;
- else
- rc = -1;
- }
- if ( chunked ) {
- while ((len = http_get_chunk_len()) > 0) {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- if ( zfile )
- zchout(ZOFILE,(CHAR)ch);
- if ( stdio )
- conoc((CHAR)ch);
- }
- if ((ch = http_inc(0)) != CR)
- break;
- if ((ch = http_inc(0)) != LF)
- break;
- }
- } else {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- if ( zfile )
- zchout(ZOFILE,(CHAR)ch);
- if ( stdio )
- conoc((CHAR)ch);
- }
- }
- if ( zfile )
- zclose(ZOFILE);
- if ( chunked ) { /* Parse Trailing Headers */
- nullline = 0;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if ( buf[i] == 10 ) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- }
- i = 0;
- } else {
- i++;
- }
- }
- }
- } else {
- rc = -1;
- }
- putexit:
- if ( array )
- http_mkarray(headers,hdcnt,array);
- if (closecon)
- http_close();
- free(request);
- for (i = 0; i < hdcnt; i++) {
- if (headers[i])
- free(headers[i]);
- }
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- http_delete(char * agent, char ** hdrlist, char * user,
- char * pwd, char array, char * remote)
- #else
- http_delete(agent, hdrlist, user, pwd, array, remote)
- char * agent; char ** hdrlist; char * user;
- char * pwd; char array; char * remote;
- #endif /* CK_ANSIC */
- {
- char * request=NULL;
- int i, j, len = 0, hdcnt = 0, rc = 0;
- int ch;
- int http_fnd = 0;
- char buf[HTTPBUFLEN], *p;
- int nullline;
- time_t mod_t;
- time_t srv_t;
- time_t local_t;
- char passwd[64];
- char b64in[128];
- char b64out[256];
- char * headers[HTTPHEADCNT];
- int closecon = 0;
- int chunked = 0;
- int first = 1;
- if (httpfd == -1)
- return(-1);
- if (array) {
- for (i = 0; i < HTTPHEADCNT; i++)
- headers[i] = NULL;
- }
- /* Compute length of request header */
- len = 11; /* DELETE */
- len += strlen(HTTP_VERSION);
- len += strlen(remote);
- len += 16;
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++)
- len += strlen(hdrlist[i]) + 2;
- }
- len += strlen(http_host_port) + 8;
- if (agent)
- len += 13 + strlen(agent);
- if (user) {
- if (!pwd) {
- readpass("Password: ",passwd,64);
- pwd = passwd;
- }
- ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
- j = b8tob64(b64in,strlen(b64in),b64out,256);
- memset(pwd,0,strlen(pwd));
- if (j < 0)
- return(-1);
- b64out[j] = '\0';
- len += j + 24;
- }
- len += 32; /* Date: */
- #ifdef HTTP_CLOSE
- len += 19; /* Connection: close */
- #endif
- len += 3; /* blank line + null */
- request = malloc(len);
- if (!request)
- return(-1);
- sprintf(request,"DELETE %s %s\r\n",remote,HTTP_VERSION);
- ckstrncat(request,"Date: ",len);
- #ifdef CMDATE2TM
- ckstrncat(request,http_now(),len);
- #else
- ckstrncat(request,...,len);
- #endif /* CMDATE2TM */
- ckstrncat(request,"\r\n",len);
- ckstrncat(request,"Host: ", len);
- ckstrncat(request,http_host_port, len);
- ckstrncat(request,"\r\n",len);
- if (agent) {
- ckstrncat(request,"User-agent: ",len);
- ckstrncat(request,agent,len);
- ckstrncat(request,"\r\n",len);
- }
- if (user) {
- ckstrncat(request,"Authorization: Basic ",len);
- ckstrncat(request,b64out,len);
- ckstrncat(request,"\r\n",len);
- }
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++) {
- ckstrncat(request,hdrlist[i],len);
- ckstrncat(request,"\r\n",len);
- }
- }
- #ifdef HTTP_CLOSE
- ckstrncat(request,"Connection: close\r\n",len);
- #endif
- ckstrncat(request,"\r\n",len);
- delreq:
- if (http_tol((CHAR *)request,strlen(request)) < 0)
- {
- http_close();
- if ( first ) {
- first--;
- http_reopen();
- goto delreq;
- }
- rc = -1;
- goto delexit;
- }
- /* Process the response headers */
- local_t = time(NULL);
- nullline = 0;
- i = 0;
- len = -1;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if (buf[i] == 10) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"HTTP",4,0)) {
- http_fnd = 1;
- j = ckindex(" ",buf,0,0,0);
- p = &buf[j];
- while (isspace(*p))
- p++;
- switch (p[0]) {
- case '1': /* Informational message */
- break;
- case '2': /* Success */
- break;
- case '3': /* Redirection */
- case '4': /* Client failure */
- case '5': /* Server failure */
- default: /* Unknown */
- if (!quiet)
- printf("Failure: Server reports %s\n",p);
- rc = -1;
- }
- http_set_code_reply(p);
- } else {
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
- len = atoi(&buf[16]);
- } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
- if ( ckindex("chunked",buf,18,0,0) != 0 )
- chunked = 1;
- debug(F101,"http_delete chunked","",chunked);
- }
- printf("%s\n",buf);
- }
- i = 0;
- } else {
- i++;
- }
- }
- if (ch < 0 && first) {
- first--;
- http_close();
- http_reopen();
- goto delreq;
- }
- if ( http_fnd == 0 ) {
- rc = -1;
- closecon = 1;
- goto delexit;
- }
- /* Any response data? */
- if ( chunked ) {
- while ((len = http_get_chunk_len()) > 0) {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- conoc((CHAR)ch);
- }
- if ((ch = http_inc(0)) != CR)
- break;
- if ((ch = http_inc(0)) != LF)
- break;
- }
- } else {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- conoc((CHAR)ch);
- }
- }
- if ( chunked ) { /* Parse Trailing Headers */
- nullline = 0;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if ( buf[i] == 10 ) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- }
- i = 0;
- } else {
- i++;
- }
- }
- }
- delexit:
- if (array)
- http_mkarray(headers,hdcnt,array);
- if (closecon)
- http_close();
- free(request);
- for (i = 0; i < hdcnt; i++) {
- if (headers[i])
- free(headers[i]);
- }
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- http_post(char * agent, char ** hdrlist, char * mime, char * user,
- char * pwd, char array, char * local, char * remote,
- char * dest, int stdio)
- #else
- http_post(agent, hdrlist, mime, user, pwd, array, local, remote, dest,
- stdio)
- char * agent; char ** hdrlist; char * mime; char * user;
- char * pwd; char array; char * local; char * remote; char * dest;
- int stdio;
- #endif /* CK_ANSIC */
- {
- char * request=NULL;
- int i, j, len = 0, hdcnt = 0, rc = 0;
- int ch;
- int http_fnd = 0;
- char buf[HTTPBUFLEN], *p;
- int nullline;
- time_t mod_t;
- time_t srv_t;
- time_t local_t;
- char passwd[64];
- char b64in[128];
- char b64out[256];
- int filelen;
- char * headers[HTTPHEADCNT];
- int closecon = 0;
- int chunked = 0;
- int zfile = 0;
- int first = 1;
- if (httpfd == -1)
- return(-1);
- if (array) {
- for (i = 0; i < HTTPHEADCNT; i++)
- headers[i] = NULL;
- }
- filelen = zchki(local);
- if (filelen < 0)
- return(-1);
- /* Compute length of request header */
- len = 9; /* POST */
- len += strlen(HTTP_VERSION);
- len += strlen(remote);
- len += 16;
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++)
- len += strlen(hdrlist[i]) + 2;
- }
- len += strlen(http_host_port) + 8;
- if (agent)
- len += 13 + strlen(agent);
- if (user) {
- if (!pwd) {
- readpass("Password: ",passwd,64);
- pwd = passwd;
- }
- ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
- j = b8tob64(b64in,strlen(b64in),b64out,256);
- memset(pwd,0,strlen(pwd));
- if (j < 0)
- return(-1);
- b64out[j] = '\0';
- len += j + 24;
- }
- len += 16 + strlen(mime); /* Content-type: */
- len += 32; /* Content-length: */
- len += 32; /* Date: */
- #ifdef HTTP_CLOSE
- len += 19; /* Connection: close */
- #endif
- len += 3; /* blank line + null */
- request = malloc(len);
- if (!request)
- return(-1);
- sprintf(request,"POST %s %s\r\n",remote,HTTP_VERSION);
- ckstrncat(request,"Date: ",len);
- ckstrncat(request,http_now(),len);
- ckstrncat(request,"\r\n",len);
- ckstrncat(request,"Host: ", len);
- ckstrncat(request,http_host_port, len);
- ckstrncat(request,"\r\n",len);
- if (agent) {
- ckstrncat(request,"User-agent: ",len);
- ckstrncat(request,agent,len);
- ckstrncat(request,"\r\n",len);
- }
- if (user) {
- ckstrncat(request,"Authorization: Basic ",len);
- ckstrncat(request,b64out,len);
- ckstrncat(request,"\r\n",len);
- }
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++) {
- ckstrncat(request,hdrlist[i],len);
- ckstrncat(request,"\r\n",len);
- }
- }
- ckstrncat(request,"Content-type: ",len);
- ckstrncat(request,mime,len);
- ckstrncat(request,"\r\n",len);
- #ifdef HTTP_CLOSE
- ckstrncat(request,"Connection: close\r\n",len);
- #endif
- sprintf(buf,"Content-length: %d\r\n",filelen); /* safe */
- ckstrncat(request,buf,len);
- ckstrncat(request,"\r\n",len);
- #ifdef COMMENT
- /* This is apparently a mistake - the previous ckstrncat() already */
- /* appended a blank line to the request. There should only be one. */
- /* Servers are not required by RFC 2616 to ignore extraneous empty */
- /* lines. -fdc, 28 Aug 2005. */
- ckstrncat(request,"\r\n",len);
- #endif /* COMMENT */
- /* Now we have the contents of the file */
- postopen:
- if (zopeni(ZIFILE,local)) {
- postreq:
- if (http_tol((CHAR *)request,strlen(request)) < 0)
- {
- http_close();
- if ( first ) {
- first--;
- http_reopen();
- goto postreq;
- }
- rc = -1;
- zclose(ZIFILE);
- goto postexit;
- }
- i = 0;
- while (zchin(ZIFILE,&ch) == 0) {
- buf[i++] = ch;
- if (i == HTTPBUFLEN) {
- http_tol((CHAR *)buf,HTTPBUFLEN);
- i = 0;
- }
- }
- if (i > 0)
- http_tol((CHAR *)buf,HTTPBUFLEN);
- zclose(ZIFILE);
- /* Process the response headers */
- local_t = time(NULL);
- nullline = 0;
- i = 0;
- len = -1;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if (buf[i] == 10) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"HTTP",4,0)) {
- http_fnd = 1;
- j = ckindex(" ",buf,0,0,0);
- p = &buf[j];
- while (isspace(*p))
- p++;
- switch (p[0]) {
- case '1': /* Informational message */
- break;
- case '2': /* Success */
- break;
- case '3': /* Redirection */
- case '4': /* Client failure */
- case '5': /* Server failure */
- default: /* Unknown */
- if (!quiet)
- printf("Failure: Server reports %s\n",p);
- rc = -1;
- }
- http_set_code_reply(p);
- } else {
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
- len = atoi(&buf[16]);
- } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
- if ( ckindex("chunked",buf,18,0,0) != 0 )
- chunked = 1;
- debug(F101,"http_post chunked","",chunked);
- }
- if (stdio)
- printf("%s\n",buf);
- }
- i = 0;
- } else {
- i++;
- }
- }
- if (ch < 0 && first) {
- first--;
- http_close();
- http_reopen();
- goto postopen;
- }
- if (http_fnd == 0) {
- rc = -1;
- closecon = 1;
- goto postexit;
- }
- /* Any response data? */
- if ( dest && dest[0] ) {
- if (zopeno(ZOFILE,dest,NULL,NULL))
- zfile = 1;
- else
- rc = -1;
- }
- if ( chunked ) {
- while ((len = http_get_chunk_len()) > 0) {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- if ( zfile )
- zchout(ZOFILE,(CHAR)ch);
- if ( stdio )
- conoc((CHAR)ch);
- }
- if ((ch = http_inc(0)) != CR)
- break;
- if ((ch = http_inc(0)) != LF)
- break;
- }
- } else {
- while (len && (ch = http_inc(0)) >= 0) {
- len--;
- if ( zfile )
- zchout(ZOFILE,(CHAR)ch);
- if ( stdio )
- conoc((CHAR)ch);
- }
- }
- if ( zfile )
- zclose(ZOFILE);
- if ( chunked ) { /* Parse Trailing Headers */
- nullline = 0;
- while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
- buf[i] = ch;
- if ( buf[i] == 10 ) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"Connection:",11,0)) {
- if ( ckindex("close",buf,11,0,0) != 0 )
- closecon = 1;
- }
- i = 0;
- } else {
- i++;
- }
- }
- }
- } else {
- rc = -1;
- }
- postexit:
- if (array)
- http_mkarray(headers,hdcnt,array);
- if (closecon)
- http_close();
- free(request);
- for (i = 0; i < hdcnt; i++) {
- if (headers[i])
- free(headers[i]);
- }
- return(rc);
- }
- int
- #ifdef CK_ANSIC
- http_connect(int socket, char * agent, char ** hdrlist, char * user,
- char * pwd, char array, char * host_port)
- #else
- http_connect(socket, agent, hdrlist, user, pwd, array, host_port)
- int socket;
- char * agent; char ** hdrlist; char * user;
- char * pwd; char array; char * host_port;
- #endif /* CK_ANSIC */
- {
- char * request=NULL;
- int i, j, len = 0, hdcnt = 0, rc = 0;
- int http_fnd = 0;
- char buf[HTTPBUFLEN], *p, ch;
- int nullline;
- time_t mod_t;
- time_t srv_t;
- time_t local_t;
- char passwd[64];
- char b64in[128];
- char b64out[256];
- char * headers[HTTPHEADCNT];
- int connected = 0;
- tcp_http_proxy_errno = 0;
- if (socket == -1)
- return(-1);
- if (array) {
- for (i = 0; i < HTTPHEADCNT; i++)
- headers[i] = NULL;
- }
- /* Compute length of request header */
- len = 12; /* CONNECT */
- len += strlen(HTTP_VERSION);
- len += strlen(host_port);
- len += (int) strlen(http_host_port) + 8;
- len += 16;
- len += strlen("Proxy-Connection: Keep-Alive\r\n");
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++)
- len += strlen(hdrlist[i]) + 2;
- }
- if (agent && agent[0])
- len += 13 + strlen(agent);
- if (user && user[0]) {
- if (!pwd) {
- readpass("Password: ",passwd,64);
- pwd = passwd;
- }
- ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
- j = b8tob64(b64in,strlen(b64in),b64out,256);
- memset(pwd,0,strlen(pwd));
- if (j < 0)
- return(-1);
- b64out[j] = '\0';
- len += j + 72;
- }
- len += 32; /* Date: */
- len += 3; /* blank line + null */
- request = malloc(len);
- if (!request)
- return(-1);
- sprintf(request,"CONNECT %s %s\r\n",host_port,HTTP_VERSION);
- ckstrncat(request,"Date: ",len);
- #ifdef CMDATE2TM
- ckstrncat(request,http_now(),len);
- #else
- strcat(request,...);
- #endif /* CMDATE2TM */
- ckstrncat(request,"\r\n",len);
- ckstrncat(request,"Host: ", len);
- ckstrncat(request,http_host_port, len);
- ckstrncat(request,"\r\n",len);
- if (agent && agent[0]) {
- ckstrncat(request,"User-agent: ",len);
- ckstrncat(request,agent,len);
- ckstrncat(request,"\r\n",len);
- }
- if (user && user[0]) {
- ckstrncat(request,"Proxy-authorization: Basic ",len);
- ckstrncat(request,b64out,len);
- ckstrncat(request,"\r\n",len);
- ckstrncat(request,"Extension: Security/Remote-Passphrase\r\n",len);
- }
- ckstrncat(request,"Proxy-Connection: Keep-Alive\r\n",len);
- if ( hdrlist ) {
- for (i = 0; hdrlist[i]; i++) {
- ckstrncat(request,hdrlist[i],len);
- ckstrncat(request,"\r\n",len);
- }
- }
- ckstrncat(request,"\r\n",len);
- len = strlen(request);
- #ifdef TCPIPLIB
- /* Send request */
- if (socket_write(socket,(CHAR *)request,strlen(request)) < 0) {
- rc = -1;
- goto connexit;
- }
- #else
- if (write(socket,(CHAR *)request,strlen(request)) < 0) { /* Send request */
- rc = -1;
- goto connexit;
- }
- #endif /* TCPIPLIB */
- /* Process the response headers */
- local_t = time(NULL);
- nullline = 0;
- i = 0;
- while (!nullline &&
- #ifdef TCPIPLIB
- (socket_read(socket,&ch,1) == 1) &&
- #else
- (read(socket,&ch,1) == 1) &&
- #endif /* TCPIPLIB */
- i < HTTPBUFLEN) {
- buf[i] = ch;
- if (buf[i] == 10) { /* found end of line */
- if (i > 0 && buf[i-1] == 13)
- i--;
- if (i < 1)
- nullline = 1;
- buf[i] = '\0';
- if (array && !nullline && hdcnt < HTTPHEADCNT)
- makestr(&headers[hdcnt++],buf);
- if (!ckstrcmp(buf,"HTTP",4,0)) {
- http_fnd = 1;
- j = ckindex(" ",buf,0,0,0);
- p = &buf[j];
- while (isspace(*p))
- p++;
- tcp_http_proxy_errno = atoi(p);
- switch (p[0]) {
- case '1': /* Informational message */
- break;
- case '2': /* Success */
- connected = 1;
- break;
- case '3': /* Redirection */
- case '4': /* Client failure */
- case '5': /* Server failure */
- default: /* Unknown */
- if (!quiet)
- printf("Failure: Server reports %s\n",p);
- rc = -1;
- }
- http_set_code_reply(p);
- } else {
- printf("%s\n",buf);
- }
- i = 0;
- } else {
- i++;
- }
- }
- if ( http_fnd == 0 )
- rc = -1;
- if (array)
- http_mkarray(headers,hdcnt,array);
- connexit:
- if ( !connected ) {
- if ( socket == ttyfd ) {
- ttclos(0);
- }
- else if ( socket == httpfd ) {
- http_close();
- }
- }
- free(request);
- for (i = 0; i < hdcnt; i++) {
- if (headers[i])
- free(headers[i]);
- }
- return(rc);
- }
- #endif /* NOHTTP */
- #ifdef CK_DNS_SRV
- #define INCR_CHECK(x,y) x += y; if (x > size + answer.bytes) goto dnsout
- #define CHECK(x,y) if (x + y > size + answer.bytes) goto dnsout
- #define NTOHSP(x,y) x[0] << 8 | x[1]; x += y
- #ifndef CKQUERYTYPE
- #ifdef UNIXWARE
- #ifndef UW7
- #define CKQUERYTYPE CHAR
- #endif /* UW7 */
- #endif /* UNIXWARE */
- #endif /* CKQUERYTYPE */
- #ifndef CKQUERYTYPE
- #define CKQUERYTYPE char
- #endif /* CKQUERYTYPE */
- /* 1 is success, 0 is failure */
- int
- locate_srv_dns(host, service, protocol, addr_pp, naddrs)
- char *host;
- char *service;
- char *protocol;
- struct sockaddr **addr_pp;
- int *naddrs;
- {
- int nout, j, count;
- union {
- unsigned char bytes[2048];
- HEADER hdr;
- } answer;
- unsigned char *p=NULL;
- CKQUERYTYPE query[MAX_DNS_NAMELEN];
- #ifdef CK_ANSIC
- const char * h;
- #else
- char * h;
- #endif /* CK_ANSIC */
- struct sockaddr *addr = NULL;
- struct sockaddr_in *sin = NULL;
- struct hostent *hp = NULL;
- int type, class;
- int priority, weight, size, len, numanswers, numqueries, rdlen;
- unsigned short port;
- #ifdef CK_ANSIC
- const
- #endif /* CK_ANSIC */
- int hdrsize = sizeof(HEADER);
- struct srv_dns_entry {
- struct srv_dns_entry *next;
- int priority;
- int weight;
- unsigned short port;
- char *host;
- };
- struct srv_dns_entry *head = NULL;
- struct srv_dns_entry *srv = NULL, *entry = NULL;
- char * s = NULL;
- nout = 0;
- addr = (struct sockaddr *) malloc(sizeof(struct sockaddr));
- if (addr == NULL)
- return 0;
- count = 1;
- /*
- * First build a query of the form:
- *
- * service.protocol.host
- *
- * which will most likely be something like:
- *
- * _telnet._tcp.host
- *
- */
- if (((int)strlen(service) + strlen(protocol) + strlen(host) + 5)
- > MAX_DNS_NAMELEN
- )
- goto dnsout;
- /* Realm names don't (normally) end with ".", but if the query
- doesn't end with "." and doesn't get an answer as is, the
- resolv code will try appending the local domain. Since the
- realm names are absolutes, let's stop that.
- But only if a name has been specified. If we are performing
- a search on the prefix alone then the intention is to allow
- the local domain or domain search lists to be expanded.
- */
- h = host + strlen (host);
- ckmakxmsg(query, sizeof(query), "_",service,"._",protocol,".", host,
- ((h > host) && (h[-1] != '.')?".":NULL),
- NULL,NULL,NULL,NULL,NULL);
- size = res_search(query, C_IN, T_SRV, answer.bytes, sizeof(answer.bytes));
- if (size < hdrsize)
- goto dnsout;
- /* We got a reply - See how many answers it contains. */
- p = answer.bytes;
- numqueries = ntohs(answer.hdr.qdcount);
- numanswers = ntohs(answer.hdr.ancount);
- p += sizeof(HEADER);
- /*
- * We need to skip over all of the questions, so we have to iterate
- * over every query record. dn_expand() is able to tell us the size
- * of compressed DNS names, so we use it.
- */
- while (numqueries--) {
- len = dn_expand(answer.bytes,answer.bytes+size,p,query,sizeof(query));
- if (len < 0)
- goto dnsout;
- INCR_CHECK(p, len + 4);
- }
- /*
- * We're now pointing at the answer records. Only process them if
- * they're actually T_SRV records (they might be CNAME records,
- * for instance).
- *
- * But in a DNS reply, if you get a CNAME you always get the associated
- * "real" RR for that CNAME. RFC 1034, 3.6.2:
- *
- * CNAME RRs cause special action in DNS software. When a name server
- * fails to find a desired RR in the resource set associated with the
- * domain name, it checks to see if the resource set consists of a CNAME
- * record with a matching class. If so, the name server includes the CNAME
- * record in the response and restarts the query at the domain name
- * specified in the data field of the CNAME record. The one exception to
- * this rule is that queries which match the CNAME type are not restarted.
- *
- * In other words, CNAMEs do not need to be expanded by the client.
- */
- while (numanswers--) {
- /* First is the name; use dn_expand() to get the compressed size. */
- len = dn_expand(answer.bytes,answer.bytes+size,p,query,sizeof(query));
- if (len < 0)
- goto dnsout;
- INCR_CHECK(p, len);
- CHECK(p,2); /* Query type */
- type = NTOHSP(p,2);
- CHECK(p, 6); /* Query class */
- class = NTOHSP(p,6); /* Also skip over 4-byte TTL */
- CHECK(p,2); /* Record data length */
- rdlen = NTOHSP(p,2);
- /*
- * If this is an SRV record, process it. Record format is:
- *
- * Priority
- * Weight
- * Port
- * Server name
- */
- if (class == C_IN && type == T_SRV) {
- CHECK(p,2);
- priority = NTOHSP(p,2);
- CHECK(p, 2);
- weight = NTOHSP(p,2);
- CHECK(p, 2);
- port = NTOHSP(p,2);
- len = dn_expand(answer.
- bytes,
- answer.bytes + size,
- p,
- query,
- sizeof(query)
- );
- if (len < 0)
- goto dnsout;
- INCR_CHECK(p, len);
- /*
- * We got everything. Insert it into our list, but make sure
- * it's in the right order. Right now we don't do anything
- * with the weight field
- */
- srv = (struct srv_dns_entry *)malloc(sizeof(struct srv_dns_entry));
- if (srv == NULL)
- goto dnsout;
- srv->priority = priority;
- srv->weight = weight;
- srv->port = port;
- makestr(&s,(char *)query); /* strdup() is not portable */
- srv->host = s;
- if (head == NULL || head->priority > srv->priority) {
- srv->next = head;
- head = srv;
- } else
- /*
- * Confusing. Insert an entry into this spot only if:
- * . The next person has a higher priority (lower
- * priorities are preferred), or:
- * . There is no next entry (we're at the end)
- */
- for (entry = head; entry != NULL; entry = entry->next)
- if ((entry->next &&
- entry->next->priority > srv->priority) ||
- entry->next == NULL) {
- srv->next = entry->next;
- entry->next = srv;
- break;
- }
- } else
- INCR_CHECK(p, rdlen);
- }
- /*
- * Now we've got a linked list of entries sorted by priority.
- * Start looking up A records and returning addresses.
- */
- if (head == NULL)
- goto dnsout;
- for (entry = head; entry != NULL; entry = entry->next) {
- hp = gethostbyname(entry->host);
- if (hp != 0) {
- /* Watch out - memset() and memcpy() are not portable... */
- switch (hp->h_addrtype) {
- case AF_INET:
- for (j = 0; hp->h_addr_list[j]; j++) {
- sin = (struct sockaddr_in *) &addr[nout++];
- memset ((char *) sin, 0, sizeof (struct sockaddr));
- sin->sin_family = hp->h_addrtype;
- sin->sin_port = htons(entry->port);
- memcpy((char *) &sin->sin_addr,
- (char *) hp->h_addr_list[j],
- sizeof(struct in_addr)); /* safe */
- if (nout + 1 >= count) {
- count += 5;
- addr = (struct sockaddr *)
- realloc((char *) addr,
- sizeof(struct sockaddr) * count);
- if (!addr)
- goto dnsout;
- }
- }
- break;
- default:
- break;
- }
- }
- }
- for (entry = head; entry != NULL;) {
- free(entry->host);
- entry->host = NULL;
- srv = entry;
- entry = entry->next;
- free(srv);
- srv = NULL;
- }
- dnsout:
- if (srv)
- free(srv);
- if (nout == 0) { /* No good servers */
- if (addr)
- free(addr);
- return 0;
- }
- *addr_pp = addr;
- *naddrs = nout;
- return 1;
- }
- #undef INCR_CHECK
- #undef CHECK
- #undef NTOHSP
- #define INCR_CHECK(x, y) x += y; if (x > size + answer.bytes) \
- return 0
- #define CHECK(x, y) if (x + y > size + answer.bytes) \
- return 0
- #define NTOHSP(x, y) x[0] << 8 | x[1]; x += y
- int
- locate_txt_rr(prefix, name, retstr)
- char *prefix, *name;
- char **retstr;
- {
- union {
- unsigned char bytes[2048];
- HEADER hdr;
- } answer;
- unsigned char *p;
- char host[MAX_DNS_NAMELEN], *h;
- int size;
- int type, class, numanswers, numqueries, rdlen, len;
- /*
- * Form our query, and send it via DNS
- */
- if (name == NULL || name[0] == '\0') {
- strcpy(host,prefix);
- } else {
- if ( strlen(prefix) + strlen(name) + 3 > MAX_DNS_NAMELEN )
- return 0;
- /* Realm names don't (normally) end with ".", but if the query
- doesn't end with "." and doesn't get an answer as is, the
- resolv code will try appending the local domain. Since the
- realm names are absolutes, let's stop that.
- But only if a name has been specified. If we are performing
- a search on the prefix alone then the intention is to allow
- the local domain or domain search lists to be expanded.
- */
- h = host + strlen (host);
- ckmakmsg(host,sizeof(host),prefix, ".", name,
- ((h > host) && (h[-1] != '.'))?".":NULL);
- }
- size = res_search(host, C_IN, T_TXT, answer.bytes, sizeof(answer.bytes));
- if (size < 0)
- return 0;
- p = answer.bytes;
- numqueries = ntohs(answer.hdr.qdcount);
- numanswers = ntohs(answer.hdr.ancount);
- p += sizeof(HEADER);
- /*
- * We need to skip over the questions before we can get to the answers,
- * which means we have to iterate over every query record. We use
- * dn_expand to tell us how long each compressed name is.
- */
- while (numqueries--) {
- len = dn_expand(answer.bytes, answer.bytes + size, p, host,
- sizeof(host));
- if (len < 0)
- return 0;
- INCR_CHECK(p, len + 4); /* Name plus type plus class */
- }
- /*
- * We're now pointing at the answer records. Process the first
- * TXT record we find.
- */
- while (numanswers--) {
- /* First the name; use dn_expand to get the compressed size */
- len = dn_expand(answer.bytes, answer.bytes + size, p,
- host, sizeof(host));
- if (len < 0)
- return 0;
- INCR_CHECK(p, len);
- /* Next is the query type */
- CHECK(p, 2);
- type = NTOHSP(p,2);
- /* Next is the query class; also skip over 4 byte TTL */
- CHECK(p,6);
- class = NTOHSP(p,6);
- /* Record data length - make sure we aren't truncated */
- CHECK(p,2);
- rdlen = NTOHSP(p,2);
- if (p + rdlen > answer.bytes + size)
- return 0;
- /*
- * If this is a TXT record, return the string. Note that the
- * string has a 1-byte length in the front
- */
- /* XXX What about flagging multiple TXT records as an error? */
- if (class == C_IN && type == T_TXT) {
- len = *p++;
- if (p + len > answer.bytes + size)
- return 0;
- *retstr = malloc(len + 1);
- if (*retstr == NULL)
- return ENOMEM;
- strncpy(*retstr, (char *) p, len);
- (*retstr)[len] = '\0';
- /* Avoid a common error. */
- if ( (*retstr)[len-1] == '.' )
- (*retstr)[len-1] = '\0';
- return 1;
- }
- }
- return 0;
- }
- #undef INCR_CHECK
- #undef CHECK
- #undef NTOHSP
- #endif /* CK_DNS_SRV */
- #ifdef TNCODE
- #ifdef CK_FORWARD_X
- #ifdef UNIX
- #include <sys/un.h>
- #define FWDX_UNIX_SOCK
- #ifndef AF_LOCAL
- #define AF_LOCAL AF_UNIX
- #endif
- #ifndef PF_LOCAL
- #define PF_LOCAL PF_UNIX
- #endif
- #ifndef SUN_LEN
- /* Evaluate to actual length of the `sockaddr_un' structure. */
- #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
- + strlen ((ptr)->sun_path))
- #endif
- #endif /* UNIX */
- int
- fwdx_create_listen_socket(screen) int screen; {
- #ifdef NOPUTENV
- return(-1);
- #else /* NOPUTENV */
- struct sockaddr_in saddr;
- int display, port, sock=-1, i;
- static char env[512];
- /*
- * X Windows Servers support multiple displays by listening on
- * one socket per display. Display 0 is port 6000; Display 1 is
- * port 6001; etc.
- *
- * We start by trying to open port 6001 so that display 0 is
- * reserved for the local X Windows Server.
- */
- for ( display=1; display < 1000 ; display++ ) {
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- debug(F111,"fwdx_create_listen_socket()","socket() < 0",sock);
- return(-1);
- }
- port = 6000 + display;
- bzero((char *)&saddr, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = inet_addr(myipaddr);
- saddr.sin_port = htons(port);
- if (bind(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
- i = errno; /* Save error code */
- #ifdef TCPIPLIB
- socket_close(sock);
- #else /* TCPIPLIB */
- close(sock);
- #endif /* TCPIPLIB */
- sock = -1;
- debug(F110,"fwdx_create_listen_socket()","bind() < 0",0);
- continue;
- }
- debug(F100,"fdwx_create_listen_socket() bind OK","",0);
- break;
- }
- if ( display > 1000 ) {
- debug(F100,"fwdx_create_listen_socket() Out of Displays","",0);
- return(-1);
- }
- if (listen(sock, 5) < 0) {
- i = errno; /* Save error code */
- #ifdef TCPIPLIB
- socket_close(sock);
- #else /* TCPIPLIB */
- close(sock);
- #endif /* TCPIPLIB */
- debug(F101,"fdwx_create_listen_socket() listen() errno","",errno);
- return(-1);
- }
- debug(F100,"fwdx_create_listen_socket() listen OK","",0);
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = sock;
- if (!myipaddr[0])
- getlocalipaddr();
- if ( myipaddr[0] )
- ckmakxmsg(env,sizeof(env),"DISPLAY=",myipaddr,":",
- ckuitoa(display),":",ckuitoa(screen),
- NULL,NULL,NULL,NULL,NULL,NULL);
- else
- ckmakmsg(env,sizeof(env),"DISPLAY=",ckuitoa(display),":",
- ckuitoa(screen));
- putenv(env);
- return(0);
- #endif /* NOPUTENV */
- }
- int
- fwdx_open_client_channel(channel) int channel; {
- char * env;
- struct sockaddr_in saddr;
- #ifdef FWDX_UNIX_SOCK
- struct sockaddr_un saddr_un = { AF_LOCAL };
- #endif /* FWDX_UNIX_SOCK */
- int colon, dot, display, port, sock, i, screen;
- int family;
- char buf[256], * host=NULL, * rest=NULL;
- #ifdef TCP_NODELAY
- int on=1;
- #endif /* TCP_NODELAY */
- debug(F111,"fwdx_create_client_channel()","channel",channel);
- for ( i=0; i<MAXFWDX ; i++ ) {
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel) {
- /* Already open */
- debug(F110,"fwdx_create_client_channel()","already open",0);
- return(0);
- }
- }
- env = getenv("DISPLAY");
- if ( !env )
- env = (char *)tn_get_display();
- if ( env )
- ckstrncpy(buf,env,256);
- else
- ckstrncpy(buf,"127.0.0.1:0.0",256);
- bzero((char *)&saddr,sizeof(saddr));
- saddr.sin_family = AF_INET;
- if (!fwdx_parse_displayname(buf,
- &family,
- &host,
- &display,
- &screen,
- &rest
- )
- ) {
- if ( host ) free(host);
- if ( rest ) free(rest);
- return(0);
- }
- if (rest) free(rest);
- #ifndef FWDX_UNIX_SOCK
- /* if $DISPLAY indicates use of unix domain sockets, but we don't support it,
- * we change things to use inet sockets on the ip loopback interface instead,
- * and hope that it works.
- */
- if (family == FamilyLocal) {
- debug(F100,"fwdx_create_client_channel() FamilyLocal","",0);
- family = FamilyInternet;
- if (host) free(host);
- if (host = malloc(strlen("localhost") + 1))
- strcpy(host, "localhost");
- else {
- return(-1);
- }
- }
- #else /* FWDX_UNIX_SOCK */
- if (family == FamilyLocal) {
- if (host) free(host);
- sock = socket(PF_LOCAL, SOCK_STREAM, 0);
- if (sock < 0)
- return(-1);
- ckmakmsg(buf,sizeof(buf),"/tmp/.X11-unix/X",ckitoa(display),NULL,NULL);
- strncpy(saddr_un.sun_path, buf, sizeof(saddr_un.sun_path));
- if (connect(sock,(struct sockaddr *)&saddr_un, SUN_LEN(&saddr_un)) < 0)
- return(-1);
- } else
- #endif /* FWDX_UNIX_SOCK */
- {
- /* Otherwise, we are assuming FamilyInternet */
- if (host) {
- ckstrncpy(buf,host,sizeof(buf));
- free(host);
- } else
- ckstrncpy(buf,myipaddr,sizeof(buf));
- debug(F111,"fwdx_create_client_channel()","display",display);
- port = 6000 + display;
- saddr.sin_port = htons(port);
- debug(F110,"fwdx_create_client_channel() ip-address",buf,0);
- saddr.sin_addr.s_addr = inet_addr(buf);
- if ( saddr.sin_addr.s_addr == (unsigned long) -1
- #ifdef INADDR_NONE
- || saddr.sin_addr.s_addr == INADDR_NONE
- #endif /* INADDR_NONE */
- )
- {
- struct hostent *host;
- host = gethostbyname(buf);
- if ( host == NULL )
- return(-1);
- host = ck_copyhostent(host);
- #ifdef HADDRLIST
- #ifdef h_addr
- /* This is for trying multiple IP addresses - see <netdb.h> */
- if (!(host->h_addr_list))
- return(-1);
- bcopy(host->h_addr_list[0],
- (caddr_t)&saddr.sin_addr,
- host->h_length
- );
- #else
- bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
- #endif /* h_addr */
- #else /* HADDRLIST */
- bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
- #endif /* HADDRLIST */
- }
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- debug(F111,"fwdx_create_client_channel()","socket() < 0",sock);
- return(-1);
- }
- if ( connect(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
- debug(F110,"fwdx_create_client_channel()","connect() failed",0);
- #ifdef TCPIPLIB
- socket_close(sock);
- #else /* TCPIPLIB */
- close(sock);
- #endif /* TCPIPLIB */
- return(-1);
- }
- #ifdef TCP_NODELAY
- setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char *)&on,sizeof(on));
- #endif /* TCP_NODELAY */
- }
- for (i = 0; i < MAXFWDX; i++) {
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == -1) {
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd = sock;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id = channel;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 1;
- debug(F111,"fwdx_create_client_channel()","socket",sock);
- return(0);
- }
- }
- return(-1);
- }
- int
- fwdx_server_avail() {
- char * env;
- struct sockaddr_in saddr;
- #ifdef FWDX_UNIX_SOCK
- struct sockaddr_un saddr_un = { AF_LOCAL };
- #endif /* FWDX_UNIX_SOCK */
- int colon, dot, display, port, sock, i, screen;
- char buf[256], *host=NULL, *rest=NULL;
- #ifdef TCP_NODELAY
- int on=1;
- #endif /* TCP_NODELAY */
- int family;
- env = getenv("DISPLAY");
- if ( !env )
- env = (char *)tn_get_display();
- if ( env )
- ckstrncpy(buf,env,256);
- else
- ckstrncpy(buf,"127.0.0.1:0.0",256);
- bzero((char *)&saddr,sizeof(saddr));
- saddr.sin_family = AF_INET;
- if (!fwdx_parse_displayname(buf,&family,&host,&display,&screen,&rest)) {
- if ( host ) free(host);
- if ( rest ) free(rest);
- return(0);
- }
- if (rest) free(rest);
- #ifndef FWDX_UNIX_SOCK
- /* if $DISPLAY indicates use of unix domain sockets, but we don't support it,
- * we change things to use inet sockets on the ip loopback interface instead,
- * and hope that it works.
- */
- if (family == FamilyLocal) {
- family = FamilyInternet;
- if (host) free(host);
- if (host = malloc(strlen("localhost") + 1))
- strcpy(host, "localhost");
- else {
- return(-1);
- }
- }
- #else /* FWDX_UNIX_SOCK */
- if (family == FamilyLocal) {
- debug(F100,"fwdx_server_avail() FamilyLocal","",0);
- if (host) free(host);
- sock = socket(PF_LOCAL, SOCK_STREAM, 0);
- if (sock < 0)
- return(0);
- ckmakmsg(buf,sizeof(buf),"/tmp/.X11-unix/X",ckitoa(display),NULL,NULL);
- strncpy(saddr_un.sun_path, buf, sizeof(saddr_un.sun_path));
- if (connect(sock,(struct sockaddr *)&saddr_un,SUN_LEN(&saddr_un)) < 0)
- return(0);
- close(sock);
- return(1);
- }
- #endif /* FWDX_UNIX_SOCK */
- /* Otherwise, we are assuming FamilyInternet */
- if (host) {
- ckstrncpy(buf,host,sizeof(buf));
- free(host);
- } else
- ckstrncpy(buf,myipaddr,sizeof(buf));
- debug(F111,"fwdx_server_avail()","display",display);
- port = 6000 + display;
- saddr.sin_port = htons(port);
- debug(F110,"fwdx_server_avail() ip-address",buf,0);
- saddr.sin_addr.s_addr = inet_addr(buf);
- if ( saddr.sin_addr.s_addr == (unsigned long) -1
- #ifdef INADDR_NONE
- || saddr.sin_addr.s_addr == INADDR_NONE
- #endif /* INADDR_NONE */
- )
- {
- struct hostent *host;
- host = gethostbyname(buf);
- if ( host == NULL ) {
- debug(F110,"fwdx_server_avail() gethostbyname() failed",
- myipaddr,0);
- return(-1);
- }
- host = ck_copyhostent(host);
- #ifdef HADDRLIST
- #ifdef h_addr
- /* This is for trying multiple IP addresses - see <netdb.h> */
- if (!(host->h_addr_list))
- return(-1);
- bcopy(host->h_addr_list[0],
- (caddr_t)&saddr.sin_addr,
- host->h_length
- );
- #else
- bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
- #endif /* h_addr */
- #else /* HADDRLIST */
- bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
- #endif /* HADDRLIST */
- }
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- debug(F111,"fwdx_server_avail()","socket() < 0",sock);
- return(0);
- }
- if ( connect(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
- debug(F110,"fwdx_server_avail()","connect() failed",0);
- #ifdef TCPIPLIB
- socket_close(sock);
- #else /* TCPIPLIB */
- close(sock);
- #endif /* TCPIPLIB */
- return(0);
- }
- #ifdef TCPIPLIB
- socket_close(sock);
- #else /* TCPIPLIB */
- close(sock);
- #endif /* TCPIPLIB */
- return(1);
- }
- int
- fwdx_open_server_channel() {
- int sock, ready_to_accept, sock2,channel,i;
- #ifdef TCP_NODELAY
- int on=1;
- #endif /* TCP_NODELAY */
- #ifdef UCX50
- static u_int saddrlen;
- #else
- static SOCKOPT_T saddrlen;
- #endif /* UCX50 */
- struct sockaddr_in saddr;
- char sb[8];
- extern char tn_msg[];
- #ifdef BSDSELECT
- fd_set rfds;
- struct timeval tv;
- #else
- #ifdef BELLSELCT
- fd_set rfds;
- #else
- fd_set rfds;
- struct timeval {
- long tv_sec;
- long tv_usec;
- } tv;
- #endif /* BELLSELECT */
- #endif /* BSDSELECT */
- unsigned short nchannel;
- unsigned char * p;
- sock = TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket;
- try_again:
- #ifdef BSDSELECT
- tv.tv_sec = tv.tv_usec = 0L;
- tv.tv_usec = 50;
- FD_ZERO(&rfds);
- FD_SET(sock, &rfds);
- ready_to_accept =
- ((select(FD_SETSIZE,
- #ifdef HPUX
- #ifdef HPUX1010
- (fd_set *)
- #else
- (int *)
- #endif /* HPUX1010 */
- #else
- #ifdef __DECC
- (fd_set *)
- #endif /* __DECC */
- #endif /* HPUX */
- &rfds, NULL, NULL, &tv) > 0) &&
- FD_ISSET(sock, &rfds));
- #else /* BSDSELECT */
- #ifdef IBMSELECT
- ready_to_accept = (select(&sock, 1, 0, 0, 50) == 1);
- #else
- #ifdef BELLSELECT
- FD_ZERO(rfds);
- FD_SET(sock, rfds);
- ready_to_accept =
- ((select(128, rfds, NULL, NULL, 50) > 0) &&
- FD_ISSET(sock, rfds));
- #else
- /* Try this - what's the worst that can happen... */
- tv.tv_sec = tv.tv_usec = 0L;
- tv.tv_usec = 50;
- FD_ZERO(&rfds);
- FD_SET(sock, &rfds);
- ready_to_accept =
- ((select(FD_SETSIZE,
- (fd_set *) &rfds, NULL, NULL, &tv) > 0) &&
- FD_ISSET(sock, &rfds));
- #endif /* BELLSELECT */
- #endif /* IBMSELECT */
- #endif /* BSDSELECT */
- if ( !ready_to_accept )
- return(0);
- if ((sock2 = accept(sock,(struct sockaddr *)&saddr,&saddrlen)) < 0) {
- int i = errno; /* save error code */
- debug(F101,"tcpsrv_open accept errno","",i);
- return(-1);
- }
- /*
- * Now we have the open socket. We must now find a channel to store
- * it in, and then notify the client.
- */
- for ( channel=0;channel<MAXFWDX;channel++ ) {
- if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].fd == -1 )
- break;
- }
- if ( channel == MAXFWDX ) {
- #ifdef TCPIPLIB
- socket_close(sock2);
- #else /* TCPIPLIB */
- close(sock2);
- #endif /* TCPIPLIB */
- return(-1);
- }
- if ( fwdx_send_open(channel) < 0 ) {
- #ifdef TCPIPLIB
- socket_close(sock2);
- #else /* TCPIPLIB */
- close(sock2);
- #endif /* TCPIPLIB */
- }
- #ifdef TCP_NODELAY
- setsockopt(sock2,IPPROTO_TCP,TCP_NODELAY,(char *)&on,sizeof(on));
- #endif /* TCP_NODELAY */
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].fd = sock2;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].id = channel;
- goto try_again;
- return(0); /* never reached */
- }
- int
- fwdx_close_channel(channel) int channel; {
- int i,fd;
- for ( i=0; i<MAXFWDX ; i++ ) {
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel)
- break;
- }
- if ( i == MAXFWDX )
- return(-1);
- fd = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd = -1;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id = -1;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
- #ifdef TCPIPLIB
- socket_close(fd);
- #else /* TCPIPLIB */
- close(fd);
- #endif /* TCPIPLIB */
- return(0);
- }
- int
- fwdx_close_all() {
- int x,fd;
- debug(F111,"fwdx_close_all()",
- "TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket",
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket);
- if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket != -1 ) {
- #ifdef TCPIPLIB
- socket_close(TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket);
- #else /* TCPIPLIB */
- close(TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket);
- #endif /* TCPIPLIB */
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
- }
- for (x = 0; x < MAXFWDX; x++) {
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd != -1) {
- fd = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
- #ifdef TCPIPLIB
- socket_close(fd);
- #else /* TCPIPLIB */
- close(fd);
- #endif /* TCPIPLIB */
- }
- }
- return(0);
- }
- /* The following definitions are for Unix */
- #ifndef socket_write
- #define socket_write(f,s,n) write(f,s,n)
- #endif /* socket_write */
- #ifndef socket_read
- #define socket_read(f,s,n) read(f,s,n)
- #endif /* socket_read */
- int
- fwdx_write_data_to_channel(channel, data, len)
- int channel; char * data; int len;
- {
- int sock, count, try=0, length = len, i;
- if ( len <= 0 )
- return(0);
- for ( i=0; i<MAXFWDX ; i++ ) {
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel)
- break;
- }
- if ( i == MAXFWDX ) {
- debug(F110,"fwdx_write_data_to_channel",
- "attempting to write to closed channel",0);
- return(-1);
- }
- sock = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd;
- debug(F111,"fwdx_write_data_to_channel","socket",sock);
- ckhexdump("fwdx_write_data_to_channel",data,len);
- fwdx_write_data_to_channel_retry:
- if ((count = socket_write(sock,data,len)) < 0) {
- int s_errno = socket_errno; /* maybe a function */
- debug(F101,"fwdx_write_data_to_channel socket_write error","",s_errno);
- #ifdef BETATEST
- printf("fwdx_write_data_to_channel error\r\n");
- #endif /* BETATEST */
- #ifdef OS2
- if (os2socketerror(s_errno) < 0)
- return(-2);
- #endif /* OS2 */
- return(-1); /* Call it an i/o error */
- }
- if (count < len) {
- debug(F111,"fwdx_write_data_to_channel socket_write",data,count);
- if (count > 0) {
- data += count;
- len -= count;
- }
- debug(F111,"fwdx_write_data_to_channel retry",data,len);
- if ( len > 0 )
- goto fwdx_write_data_to_channel_retry;
- }
- debug(F111,"fwdx_write_data_to_channel complete",data,length);
- return(length); /* success - return total length */
- }
- VOID
- fwdx_check_sockets(fd_set *ibits)
- {
- int x, sock, channel, bytes;
- static char buffer[32000];
- debug(F100,"fwdx_check_sockets()","",0);
- if ( sstelnet && !TELOPT_ME(TELOPT_FORWARD_X) ||
- !sstelnet && !TELOPT_U(TELOPT_FORWARD_X)) {
- debug(F110,"fwdx_check_sockets()","TELOPT_FORWARD_X not negotiated",0);
- return;
- }
- for (x = 0; x < MAXFWDX; x++) {
- if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd == -1 ||
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend )
- continue;
- sock = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd;
- if (FD_ISSET(sock, ibits))
- {
- channel = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id;
- debug(F111,"fwdx_check_sockets()","channel set",channel);
- bytes = socket_read(sock, buffer, sizeof(buffer));
- if (bytes > 0)
- fwdx_send_data_from_channel(channel, buffer, bytes);
- else if (bytes == 0) {
- fwdx_close_channel(channel);
- fwdx_send_close(channel);
- }
- }
- }
- }
- int
- fwdx_init_fd_set(fd_set *ibits)
- {
- int x,set=0,cnt=0;
- if ( sstelnet && !TELOPT_ME(TELOPT_FORWARD_X) ||
- !sstelnet && !TELOPT_U(TELOPT_FORWARD_X)) {
- debug(F110,"fwdx_init_fd_set()","TELOPT_FORWARD_X not negotiated",0);
- return(0);
- }
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket != -1) {
- set++;
- FD_SET(TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket, ibits);
- }
- for (x = 0; x < MAXFWDX; x++) {
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd != -1) {
- cnt++;
- if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend)
- continue;
- set++;
- FD_SET(TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd, ibits);
- }
- }
- if (set + cnt == 0) {
- return(-1);
- } else {
- return(set);
- }
- }
- #ifdef NT
- VOID
- fwdx_thread( VOID * dummy )
- {
- fd_set ifds;
- struct timeval tv;
- extern int priority;
- int n;
- setint();
- SetThreadPrty(priority,isWin95() ? 3 : 11);
- while ( !sstelnet && TELOPT_U(TELOPT_FORWARD_X) ||
- sstelnet && TELOPT_ME(TELOPT_FORWARD_X))
- {
- FD_ZERO(&ifds);
- n = fwdx_init_fd_set(&ifds);
- if (n > 0) {
- tv.tv_sec = 0;
- tv.tv_usec = 2500;
- if ( select(FD_SETSIZE, &ifds, NULL, NULL, &tv) > 0 )
- fwdx_check_sockets(&ifds);
- } else if (n < 0) {
- TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
- ckThreadEnd(NULL);
- } else {
- sleep(1);
- }
- }
- }
- #endif /* NT */
- #endif /* CK_FORWARD_X */
- #endif /* TNCODE */
- #endif /* NETCONN */
|