ckcnet.c 439 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448
  1. char *cknetv = "Network support, 9.0.297, 14 Jul 2011";
  2. /* C K C N E T -- Network support */
  3. /*
  4. Copyright (C) 1985, 2011,
  5. Trustees of Columbia University in the City of New York.
  6. All rights reserved. See the C-Kermit COPYING.TXT file or the
  7. copyright text in the ckcmai.c module for disclaimer and permissions.
  8. */
  9. /*
  10. REMINDER: Any changes made to this file that other modules depend must
  11. also be made to cklnet.c (for VOS) until such time as cklnet.c and this
  12. module are merged back together.
  13. NOTE TO CONTRIBUTORS: This file, and all the other shared (ckc and cku)
  14. C-Kermit source files, must be compatible with C preprocessors that support
  15. only #ifdef, #else, #endif, #define, and #undef. Please do not use #if,
  16. logical operators, or other preprocessor features in this module. Also,
  17. don't use any ANSI C constructs except within #ifdef CK_ANSIC..#endif.
  18. Authors:
  19. Frank da Cruz (fdc@columbia.edu),
  20. Columbia University Academic Information Systems, New York City.
  21. Jeffrey E Altman (jaltman@secure-endpoints.com) -- Primary
  22. maintainer/developer since about 1996.
  23. netopen() routine for TCP/IP originally by Ken Yap, Rochester University
  24. (ken@cs.rochester.edu) (no longer at that address).
  25. Missing pieces for Excelan sockets library from William Bader.
  26. Telnet protocol by Frank da Cruz and Jeffrey Altman.
  27. Rlogin protocol by Jeffrey E Altman.
  28. SSL support adapted by Jeffrey E Altman from work done by
  29. Tim Hudson <tjh@cryptosoft.com> +61 7 32781581
  30. TLS support by Jeffrey E Altman.
  31. HTTP support by Jeffrey E Altman.
  32. TGV MultiNet code by Frank da Cruz.
  33. MultiNet code adapted to WIN/TCP by Ray Hunter of TWG.
  34. MultiNet code adapted to DEC TCP/IP by Lee Tibbert of DEC and Frank da Cruz.
  35. TCP/IP support adapted to IBM TCP/IP 1.2.1,2.0 for OS/2 by Kai Uwe Rommel.
  36. CMU-OpenVMS/IP modifications by Mike O'Malley, Digital (DEC).
  37. X.25 support by Marcello Frutig, Catholic University,
  38. Rio de Janeiro, Brazil (frutig@rnp.impa.br) with fixes from
  39. Stefaan Eeckels, Eurokom, Luxembourg.
  40. David Lane added support for Stratus VOS X.25 1996.
  41. Stephen Riehm added support for IBM AIX X.25 in April 1998.
  42. Other contributions as indicated in the code.
  43. */
  44. #define CKCNET_C
  45. #include "ckcsym.h"
  46. #include "ckcdeb.h"
  47. #include "ckcker.h"
  48. #include "ckcasc.h"
  49. #ifdef I386IX /* Has to come before ckcnet.h in */
  50. #include <errno.h> /* this version, but after in others */
  51. #endif /* I386IX */
  52. #include "ckcnet.h" /* which includes ckctel.h */
  53. #ifdef CK_SSL
  54. #include "ck_ssl.h"
  55. #endif /* CK_SSL */
  56. #ifdef CK_DNS_SRV
  57. #ifdef OS2
  58. #ifdef NT
  59. #include <wshelper.h>
  60. #else /* NT */
  61. /* !Error OS/2 does not support DNS Service Records. */
  62. #endif /* NT */
  63. #else /* OS2 */
  64. #include <arpa/inet.h>
  65. #ifdef USE_NAMESER_COMPAT
  66. #include <arpa/nameser_compat.h>
  67. #endif /* USE_NAMESER_COMPAT */
  68. #ifdef MINIX3
  69. #include <net/gen/resolv.h>
  70. #include <net/gen/nameser.h>
  71. #else
  72. #include <arpa/nameser.h>
  73. #include <resolv.h>
  74. #endif /* MINIX 3 */
  75. #ifndef PS2AIX10
  76. #ifndef BSD4
  77. #ifndef I386IX
  78. #ifndef RTAIX
  79. #include <netdb.h>
  80. #endif /* RTAIX */
  81. #endif /* I386IX */
  82. #endif /* BSD4 */
  83. #endif /* PS2AIX10 */
  84. #endif /* OS2 */
  85. #ifndef T_SRV
  86. #define T_SRV 33
  87. #endif /* T_SRV */
  88. #ifndef T_TXT
  89. #define T_TXT 16
  90. #endif /* T_TXT */
  91. /* for old Unixes and friends ... */
  92. #ifndef MAXHOSTNAMELEN
  93. #define MAXHOSTNAMELEN 64
  94. #endif /* MAXHOSTNAMELEN */
  95. #define MAX_DNS_NAMELEN (15*(MAXHOSTNAMELEN + 1)+1)
  96. #endif /* CK_DNS_SRV */
  97. #ifdef NONET
  98. #ifdef TCPIPLIB
  99. #undef TCPIPLIB
  100. #endif /* TCPIPLIB */
  101. #endif /* NONET */
  102. #ifndef NOMHHOST
  103. #ifdef datageneral
  104. #define NOMHHOST
  105. #else
  106. #ifdef HPUX5WINTCP
  107. #define NOMHHOST
  108. #endif /* HPUX5WINTCP */
  109. #endif /* datageneral */
  110. #endif /* NOMHHOST */
  111. #ifdef INADDRX
  112. struct in_addr inaddrx;
  113. #endif /* INADDRX */
  114. int ttnet = NET_NONE; /* Network type */
  115. int ttnproto = NP_DEFAULT; /* Network virtual terminal protocol */
  116. /* 0 = don't lowercase username for Rlogin/Telnet protocol */
  117. /* nonzero = do lowercase it. Add a SET command if necessary... */
  118. #ifdef VMS
  119. int ck_lcname = 1;
  120. #else
  121. int ck_lcname = 0;
  122. #endif /* VMS */
  123. extern int /* External variables */
  124. duplex, debses, seslog, sessft, wasclosed,
  125. ttyfd, quiet, msgflg, what, nettype, ttmdm;
  126. #ifdef IKSD
  127. extern int inserver;
  128. #endif /* IKSD */
  129. char myipaddr[20] = { '\0' }; /* Global copy of my IP address */
  130. char hostipaddr[64] = { '\0' }; /* Global copy of remote IP address */
  131. #ifdef NETCONN
  132. /* Don't need any of this if there is no network support. */
  133. #ifndef OS2
  134. /* Current fd-swapping hack is not thread-safe */
  135. #define HTTP_BUFFERING
  136. #endif /* OS2 */
  137. #ifdef HTTP_BUFFERING
  138. #define HTTP_INBUFLEN 8192
  139. static char http_inbuf[HTTP_INBUFLEN];
  140. static int http_bufp = 0, http_count;
  141. #endif /* HTTP_BUFFERING */
  142. /*
  143. NETLEBUF is (must be) defined for those platforms that call this
  144. module to do network i/o (e.g. netinc(), nettchk(), etc) rather
  145. than doing it themselves (ttinc(), ttchk(), etc). In this case
  146. the Telnet local-echo buffers and routines are defined and referenced
  147. here, rather than in the ck?tio.c module.
  148. */
  149. #ifdef NETLEBUF
  150. #define LEBUFSIZ 4096
  151. int ttpush = -1, le_data = 0; /* These are seen from outside */
  152. static CHAR le_buf[LEBUFSIZ]; /* These are used internally */
  153. static int le_start = 0, le_end = 0;
  154. int tt_push_inited = 0;
  155. #endif /* NETLEBUF */
  156. #ifdef CK_SOCKS /* SOCKS Internet relay package */
  157. #ifdef CK_SOCKS5 /* SOCKS 5 */
  158. #define accept SOCKSaccept
  159. #define bind SOCKSbind
  160. #define connect SOCKSconnect
  161. #define getsockname SOCKSgetsockname
  162. #define listen SOCKSlisten
  163. #else /* Not SOCKS 5 */
  164. #define accept Raccept
  165. #define bind Rbind
  166. #define connect Rconnect
  167. #define getsockname Rgetsockname
  168. #define listen Rlisten
  169. #endif /* CK_SOCKS5 */
  170. #endif /* CK_SOCKS */
  171. #ifdef DEC_TCPIP
  172. #include <time.h>
  173. #include <inet.h>
  174. #endif /* DEC_TCPIP */
  175. /* Also see ckcnet.h -- hmmm, why don't we always include inet.h? */
  176. #ifdef HPUX
  177. #ifndef HPUX7 /* HPUX 7.00 doesn't have it */
  178. #ifndef HPUX6 /* HPUX 6.00 doesn't have it */
  179. #include <arpa/inet.h> /* For inet_ntoa() prototype */
  180. #endif /* HPUX6 */
  181. #endif /* HPUX7 */
  182. #endif /* HPUX */
  183. #ifdef CMU_TCPIP
  184. #include <time.h>
  185. #endif /* CMU_TCPIP */
  186. #ifndef NODCLTIMEVAL
  187. #ifdef DCLTIMEVAL /* UnixWare 7 */
  188. struct timeval { /* And define these ourselves. */
  189. long tv_sec; /* (see comments in ckutio.c) */
  190. long tv_usec;
  191. };
  192. struct timezone {
  193. int tz_minuteswest;
  194. int tz_dsttime;
  195. };
  196. #endif /* DCLTIMEVAL */
  197. #endif /* NODCLTIMEVAL */
  198. #ifdef WINTCP
  199. #include <setjmp.h>
  200. #include <signal.h>
  201. #include <sys/time.h>
  202. /*
  203. The WIN/TCP code path is the same as that for MultiNet.
  204. Only the routine names have changed ...
  205. */
  206. #define socket_read netread
  207. #define socket_ioctl ioctl
  208. #define socket_write netwrite
  209. #define socket_close netclose
  210. #ifdef OLD_TWG /* some routines have evolved */
  211. extern int vmserrno, uerrno;
  212. #define socket_errno uerrno
  213. #define socket_perror perror /* which uses errno, not uerrno! */
  214. #else
  215. #define socket_errno errno
  216. #define socket_perror win$perror
  217. #endif /* OLD_TWG */
  218. #else /* Not WINTCP */
  219. #ifdef OSF13
  220. #ifdef CK_ANSIC
  221. #ifdef _NO_PROTO
  222. #undef _NO_PROTO
  223. #endif /* _NO_PROTO */
  224. #endif /* CK_ANSIC */
  225. #endif /* OSF13 */
  226. #ifndef I386IX
  227. #ifndef HPUXPRE65
  228. #include <errno.h> /* Error number symbols */
  229. #else
  230. #ifndef ERRNO_INCLUDED
  231. #include <errno.h> /* Error number symbols */
  232. #endif /* ERRNO_INCLUDED */
  233. #endif /* HPUXPRE65 */
  234. #endif /* I386IX */
  235. #include <signal.h> /* Everybody needs this */
  236. #ifdef ZILOG /* Zilog has different name for this */
  237. #include <setret.h>
  238. #else
  239. #include <setjmp.h>
  240. #endif /* ZILOG */
  241. #endif /* WINTCP */
  242. #ifdef datageneral /* Data General AOS/VS */
  243. #include <:usr:include:vs_tcp_errno.h>
  244. #include <:usr:include:sys:vs_tcp_types.h>
  245. #ifdef SELECT
  246. /*
  247. NOTE: This can be compiled and linked OK with SELECT defined
  248. but it doesn't work at all. Anybody who cares and knows how
  249. to fix it, feel free.
  250. */
  251. #include <:usr:include:sys:vs_tcp_time.h>
  252. #endif /* SELECT */
  253. #include <:usr:include:sys:socket.h>
  254. #include <:usr:include:netinet:in.h>
  255. #include <:usr:include:netdb.h>
  256. #endif /* datageneral */
  257. #ifndef socket_errno
  258. #define socket_errno errno
  259. #endif /* socket_errno */
  260. #ifdef TNCODE
  261. extern int tn_deb;
  262. #endif /* TNCODE */
  263. int tcp_rdns = /* Reverse DNS lookup */
  264. #ifdef DEC_TCPIP_OLD
  265. SET_OFF /* Doesn't seem to work in UCX */
  266. #else
  267. SET_AUTO
  268. #endif /* DEC_TCPIP */
  269. ;
  270. #ifdef CK_DNS_SRV
  271. int tcp_dns_srv = SET_OFF;
  272. #endif /* CK_DNS_SRV */
  273. _PROTOTYP( char * cmcvtdate, (char *, int) );
  274. #ifdef RLOGCODE
  275. _PROTOTYP( int rlog_ctrl, (CHAR *, int) );
  276. _PROTOTYP( static int rlog_oob, (CHAR *, int) );
  277. #ifndef TCPIPLIB
  278. _PROTOTYP( static SIGTYP rlogoobh, ( int ) );
  279. #endif /* TCPIPLIB */
  280. _PROTOTYP( static int rlog_ini, (CHAR *, int,
  281. struct sockaddr_in *,
  282. struct sockaddr_in *) );
  283. int rlog_mode = RL_COOKED;
  284. int rlog_stopped = 0;
  285. int rlog_inband = 0;
  286. #endif /* RLOGCODE */
  287. #ifndef NOICP
  288. extern int doconx; /* CONNECT-class command active */
  289. #endif /* NOICP */
  290. #ifdef IBMX25
  291. /* This variable should probably be generalised for true client/server
  292. * support - ie: the fd of the listening server, accepted calls should
  293. * be forked or at least handled via a second fd (for IBM's X.25 -
  294. * ttyfd always holds the active fd - ie the server becomes inactive
  295. * as long as a client is connected, and becomes active again when the
  296. * connection is closed)
  297. */
  298. int x25serverfd = 0; /* extern in ckcnet.h */
  299. int x25seqno = 0; /* Connection sequence number */
  300. int x25lastmsg = -1; /* A cheapskate's state table */
  301. #define X25_CLOSED 0 /* Default state: no connection, no STREAM */
  302. #define X25_SETUP 1 /* X.25 has been set up (no connection) */
  303. #define X25_CONNECTED 2 /* X.25 connection has been established */
  304. int x25_state = X25_CLOSED; /* Default state */
  305. #endif /* IBMX25 */
  306. #ifndef DEBUG
  307. #define deblog 0
  308. #endif /* DEBUG */
  309. #ifdef CK_NAWS /* Negotiate About Window Size */
  310. #ifdef RLOGCODE
  311. _PROTOTYP( int rlog_naws, (void) );
  312. #endif /* RLOGCODE */
  313. #endif /* CK_NAWS */
  314. #ifdef OS2 /* For terminal type name string */
  315. #include "ckuusr.h"
  316. #ifndef NT
  317. #include <os2.h>
  318. #undef COMMENT
  319. #endif /* NT */
  320. #include "ckocon.h"
  321. extern int tt_type, max_tt;
  322. extern struct tt_info_rec tt_info[];
  323. extern char ttname[];
  324. #else
  325. #ifdef CK_AUTHENTICATION
  326. #include "ckuusr.h"
  327. #endif /* CK_AUTHENTICATION */
  328. #endif /* OS2 */
  329. #ifdef NT
  330. extern int winsock_version;
  331. #endif /* NT */
  332. #ifdef CK_AUTHENTICATION
  333. #include "ckuath.h"
  334. #endif /* CK_AUTHENTICATION */
  335. #include "ckcsig.h"
  336. #ifndef OS2 /* For timeout longjumps */
  337. static ckjmpbuf njbuf;
  338. #endif /* OS2 */
  339. #define NAMECPYL 1024 /* Local copy of hostname */
  340. char namecopy[NAMECPYL]; /* Referenced by ckctel.c */
  341. char namecopy2[NAMECPYL]; /* Referenced by ckctel.c */
  342. #ifndef NOHTTP
  343. char http_host_port[NAMECPYL]; /* orig host/port necessary for http */
  344. char http_ip[20] = { '\0' }; /* ip address of host */
  345. char http_port = 0;
  346. int http_ssl = 0;
  347. char * http_agent = 0;
  348. int httpfd = -1; /* socket for http connections */
  349. int http_code = 0;
  350. #define HTTPBUFLEN 1024
  351. char http_reply_str[HTTPBUFLEN] = "";
  352. #endif /* NOHTTP */
  353. char ipaddr[20] = { '\0' }; /* Global copy of IP address */
  354. unsigned long myxipaddr = 0L; /* Ditto as a number */
  355. #endif /* NETCONN */
  356. char *tcp_address = NULL; /* Preferred IP Address */
  357. extern char uidbuf[]; /* User ID buffer */
  358. extern char pwbuf[]; /* Password buffer */
  359. #ifndef NOHTTP
  360. char * tcp_http_proxy = NULL; /* Name[:port] of http proxy server */
  361. int tcp_http_proxy_errno = 0;
  362. char * tcp_http_proxy_user = NULL;
  363. char * tcp_http_proxy_pwd = NULL;
  364. char * tcp_http_proxy_agent = NULL;
  365. #define HTTPCPYL 1024
  366. static char proxycopy[HTTPCPYL];
  367. #endif /* NOHTTP */
  368. #ifdef OS2
  369. extern int tt_rows[], tt_cols[];
  370. extern int tt_status[VNUM];
  371. #else /* OS2 */
  372. extern int tt_rows, tt_cols; /* Everybody has this */
  373. #endif /* OS2 */
  374. extern int cmd_cols, cmd_rows;
  375. #ifdef STREAMING /* Use blocking writes for streaming */
  376. extern int streaming;
  377. #endif /* STREAMING */
  378. #ifdef NT
  379. extern int WSASafeToCancel;
  380. int win95selectbug = 0; /* For TCP/IP stacks whose select() */
  381. /* always fails on write requests such as Cisco and Quarterdeck */
  382. #define stricmp _stricmp
  383. #endif /* NT */
  384. #ifndef NOTCPOPTS
  385. /* Skip all this if NOTCPOPTS specified. */
  386. #ifdef SOL_SOCKET
  387. #ifdef TCP_NODELAY
  388. int tcp_nodelay = 0; /* Nagle algorithm TCP_NODELAY */
  389. #endif /* TCP_NODELAY */
  390. #ifdef SO_DONTROUTE
  391. int tcp_dontroute = 0;
  392. #endif /* SO_DONTROUTE */
  393. #ifdef SO_LINGER
  394. int tcp_linger = 0; /* SO_LINGER */
  395. int tcp_linger_tmo = 0; /* SO_LINGER timeout */
  396. #endif /* SO_LINGER */
  397. #ifdef HPUX /* But the data structures */
  398. #ifndef HPUX8 /* needed for linger are not */
  399. #ifndef HPUX9 /* defined in HP-UX versions */
  400. #ifndef HPUX10 /* prior to 8.00. */
  401. #ifdef SO_LINGER
  402. #undef SO_LINGER
  403. #endif /* SO_LINGER */
  404. #endif /* HPUX10 */
  405. #endif /* HPUX9 */
  406. #endif /* HPUX8 */
  407. #endif /* HPUX */
  408. #ifndef SO_OOBINLINE /* Hopefully only HP-UX 7.0 */
  409. #define SO_OOBINLINE 0x0100
  410. #endif /* SO_OOBINLINE */
  411. #ifndef TCPSNDBUFSIZ
  412. #ifdef VMS
  413. #ifdef __alpha
  414. #define TCPSNDBUFSIZ 16384
  415. #endif /* __alpha */
  416. #endif /* VMS */
  417. #endif /* TCPSNDBUFSIZ */
  418. #ifndef TCPSNDBUFSIZ
  419. #define TCPSNDBUFSIZ -1
  420. #endif /* TCPSNDBUFSIZ */
  421. #ifdef SO_SNDBUF
  422. int tcp_sendbuf = TCPSNDBUFSIZ;
  423. #endif /* SO_SNDBUF */
  424. #ifdef SO_RCVBUF
  425. int tcp_recvbuf = -1;
  426. #endif /* SO_RCVBUF */
  427. #ifdef SO_KEEPALIVE
  428. int tcp_keepalive = 1;
  429. #endif /* SO_KEEPALIVE */
  430. #endif /* SOL_SOCKET */
  431. #endif /* NOTCPOPTS */
  432. #ifndef NETCONN
  433. /*
  434. Network support not defined.
  435. Dummy functions here in case #ifdef's forgotten elsewhere.
  436. */
  437. int /* Open network connection */
  438. netopen(name, lcl, nett) char *name; int *lcl, nett; {
  439. return(-1);
  440. }
  441. int /* Close network connection */
  442. netclos() {
  443. return(-1);
  444. }
  445. int /* Check network input buffer */
  446. nettchk() {
  447. return(-1);
  448. }
  449. int /* Flush network input buffer */
  450. netflui() {
  451. return(-1);
  452. }
  453. int /* Send network BREAK */
  454. netbreak() {
  455. return(-1);
  456. }
  457. int /* Input character from network */
  458. netinc(timo) int timo; {
  459. return(-1);
  460. }
  461. int /* Output character to network */
  462. #ifdef CK_ANSIC
  463. nettoc(CHAR c)
  464. #else
  465. nettoc(c) CHAR c;
  466. #endif /* CK_ANSIC */
  467. /* nettoc */ {
  468. return(-1);
  469. }
  470. int
  471. nettol(s,n) CHAR *s; int n; {
  472. return(-1);
  473. }
  474. #else /* NETCONN is defined (much of this module...) */
  475. #ifdef NETLEBUF
  476. VOID
  477. le_init() { /* LocalEchoInit() */
  478. int i;
  479. for (i = 0; i < LEBUFSIZ; i++)
  480. le_buf[i] = '\0';
  481. le_start = 0;
  482. le_end = 0;
  483. le_data = 0;
  484. tt_push_inited = 1;
  485. }
  486. VOID
  487. le_clean() { /* LocalEchoCleanup() */
  488. le_init();
  489. return;
  490. }
  491. int
  492. le_inbuf() {
  493. int rc = 0;
  494. if (le_start != le_end) {
  495. rc = (le_end -
  496. le_start +
  497. LEBUFSIZ) % LEBUFSIZ;
  498. }
  499. return(rc);
  500. }
  501. int
  502. #ifdef CK_ANSIC
  503. le_putchar(CHAR ch)
  504. #else
  505. le_putchar(ch) CHAR ch;
  506. #endif /* CK_ANSIC */
  507. /* le_putchar */ {
  508. if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
  509. debug(F110,"le_putchar","buffer is full",0);
  510. return(-1);
  511. }
  512. le_buf[le_end++] = ch;
  513. if (le_end == LEBUFSIZ)
  514. le_end = 0;
  515. le_data = 1;
  516. return(0);
  517. }
  518. int
  519. #ifdef CK_ANSIC
  520. le_puts(CHAR * s, int n)
  521. #else
  522. le_puts(s,n) CHAR * s; int n;
  523. #endif /* CK_ANSIC */
  524. /* le_puts */ {
  525. int rc = 0;
  526. int i = 0;
  527. CHAR * p = (CHAR *)"le_puts";
  528. ckhexdump(p,s,n);
  529. for (i = 0; i < n; i++)
  530. rc = le_putchar((char)s[i]);
  531. debug(F101,"le_puts","",rc);
  532. return(rc);
  533. }
  534. int
  535. #ifdef CK_ANSIC
  536. le_putstr(CHAR * s)
  537. #else
  538. le_putstr(s) CHAR * s;
  539. #endif /* CK_ANSIC */
  540. /* le_puts */ {
  541. CHAR * p;
  542. int rc = 0;
  543. p = (CHAR *)"le_putstr";
  544. ckhexdump(p,s,(int)strlen((char *)s));
  545. for (p = s; *p && !rc; p++)
  546. rc = le_putchar(*p);
  547. return(rc);
  548. }
  549. int
  550. #ifdef CK_ANSIC
  551. le_getchar(CHAR * pch)
  552. #else /* CK_ANSIC */
  553. le_getchar(pch) CHAR * pch;
  554. #endif /* CK_ANSIC */
  555. /* le_gatchar */ {
  556. int rc = 0;
  557. if (le_start != le_end) {
  558. *pch = le_buf[le_start];
  559. le_buf[le_start] = 0;
  560. le_start++;
  561. if (le_start == LEBUFSIZ)
  562. le_start = 0;
  563. if (le_start == le_end) {
  564. le_data = 0;
  565. }
  566. rc++;
  567. } else {
  568. *pch = 0;
  569. }
  570. return(rc);
  571. }
  572. #endif /* NETLEBUF */
  573. #ifdef VMS
  574. /*
  575. In edit 190, we moved tn_ini() to be called from within netopen().
  576. But tn_ini() calls ttol(), and ttol() checks to see if it's a net
  577. connection, but the flag for that isn't set until after netopen()
  578. is finished. Since, in this module, we are always doing network
  579. output anyway, we just call nettol() directly, instead of going thru
  580. ttol(). Only needed for VMS, since UNIX, AOS/VS, and VOS can handle
  581. net connections just like regular connections in ttol(), and OS/2
  582. has a special routine for this.
  583. */
  584. #define ttol nettol
  585. #endif /* VMS */
  586. int tcpsrfd = -1;
  587. #ifdef CK_KERBEROS
  588. char * krb5_d_principal = NULL; /* Default principal */
  589. char * krb5_d_instance = NULL; /* Default instance */
  590. char * krb5_d_realm = NULL; /* Default realm */
  591. char * krb5_d_cc = NULL; /* Default credentials cache */
  592. char * krb5_d_srv = NULL; /* Default Service */
  593. int krb5_d_lifetime = 600; /* Default lifetime (10 hours) */
  594. int krb5_d_forwardable = 0; /* creds not forwardable */
  595. int krb5_d_proxiable = 0; /* creds not proxiable */
  596. int krb5_d_renewable = 0; /* creds not renewable (0 min) */
  597. int krb5_autoget = 1; /* Autoget TGTs */
  598. int krb5_autodel = 0; /* Auto delete TGTs */
  599. int krb5_d_getk4 = 0; /* K5 Kinit gets K4 TGTs */
  600. int krb5_checkaddrs = 1; /* Check TGT Addrs */
  601. int krb5_d_no_addresses = 0; /* Do not include IP Addresses */
  602. char * krb5_d_addrs[KRB5_NUM_OF_ADDRS+1]={NULL,NULL}; /* Addrs to include */
  603. int krb5_errno = 0; /* Last K5 errno */
  604. char * krb5_errmsg = NULL; /* Last K5 errmsg */
  605. char * k5_keytab = NULL;
  606. char * krb4_d_principal = NULL; /* Default principal */
  607. char * krb4_d_realm = NULL; /* Default realm */
  608. char * krb4_d_srv = NULL; /* Default Service */
  609. int krb4_d_lifetime = 600; /* Default lifetime (10 hours) */
  610. int krb4_d_preauth = 1; /* Use preauth requests */
  611. char * krb4_d_instance = NULL; /* Default instance */
  612. int krb4_autoget = 1; /* Autoget TGTs */
  613. int krb4_autodel = 0; /* Auto delete TGTs */
  614. int krb4_checkaddrs = 1; /* Check TGT Addrs */
  615. char * k4_keytab = NULL;
  616. int krb4_errno = 0; /* Last K4 errno */
  617. char * krb4_errmsg = NULL; /* Last K4 errmsg */
  618. struct krb_op_data krb_op = { /* Operational data structure */
  619. 0, NULL /* (version, cachefile) */
  620. };
  621. struct krb4_init_data krb4_init = { /* Kerberos 4 INIT data structure */
  622. 0, NULL, NULL, NULL, NULL
  623. };
  624. struct krb5_init_data krb5_init = { /* Kerberos 5 INIT data structure */
  625. 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0,
  626. { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  627. NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
  628. 0
  629. };
  630. struct krb5_list_cred_data krb5_lc = { /* List Credentials data structure */
  631. 0, 0, 0
  632. };
  633. int krb_action = -1; /* Kerberos action to perform */
  634. #ifndef CK_AUTHENTICATION
  635. char *
  636. ck_krb4_getrealm() {
  637. return("");
  638. }
  639. char *
  640. ck_krb5_getrealm(cc) char * cc; {
  641. return("");
  642. }
  643. char *
  644. ck_krb4_getprincipal() {
  645. return("");
  646. }
  647. char *
  648. ck_krb5_getprincipal(cc) char * cc; {
  649. return("");
  650. }
  651. #endif /* CK_AUTHENTICATION */
  652. /* I N I _ K E R B -- Initialize Kerberos data */
  653. VOID
  654. ini_kerb() {
  655. int i;
  656. krb_action = -1; /* No action specified */
  657. krb_op.version = 0; /* Kerberos version (none) */
  658. krb_op.cache = NULL; /* Cache file (none) */
  659. /* Kerberos 5 */
  660. krb5_init.forwardable = krb5_d_forwardable; /* Init switch values... */
  661. krb5_init.proxiable = krb5_d_proxiable;
  662. krb5_init.lifetime = krb5_d_lifetime;
  663. krb5_init.renew = 0;
  664. krb5_init.renewable = krb5_d_renewable;
  665. krb5_init.validate = 0;
  666. krb5_init.no_addresses = krb5_d_no_addresses;
  667. krb5_init.getk4 = krb5_d_getk4;
  668. if (krb5_init.postdate) {
  669. free(krb5_init.postdate);
  670. krb5_init.postdate = NULL;
  671. }
  672. if (krb5_init.service) {
  673. free(krb5_init.service);
  674. krb5_init.service = NULL;
  675. }
  676. if (!krb5_d_cc || !krb5_d_cc[0]) { /* Set default cache */
  677. char * p;
  678. p = ck_krb5_get_cc_name();
  679. makestr(&krb5_d_cc,(p && p[0]) ? p : NULL);
  680. }
  681. if (!krb5_d_realm || !krb5_d_realm[0]) { /* Set default realm */
  682. char * p;
  683. p = ck_krb5_getrealm(krb5_d_cc);
  684. makestr(&krb5_d_realm,(p && p[0]) ? p : NULL);
  685. }
  686. makestr(&krb5_init.instance,krb5_d_instance);
  687. makestr(&krb5_init.realm,krb5_d_realm); /* Set realm from default */
  688. if (krb5_init.password) {
  689. memset(krb5_init.password,0xFF,strlen(krb5_init.password));
  690. free(krb5_init.password);
  691. krb5_init.password = NULL;
  692. }
  693. if (!krb5_d_principal) { /* Default principal */
  694. /* a Null principal indicates the user should be prompted */
  695. char * p = ck_krb5_getprincipal(krb5_d_cc);
  696. if (!p || !(*p))
  697. p = (char *)uidbuf; /* Principal = user */
  698. makestr(&krb5_d_principal,(p && p[0]) ? p : NULL);
  699. }
  700. makestr(&krb5_init.principal,krb5_d_principal);
  701. for (i = 0; i <= KRB5_NUM_OF_ADDRS; i++) {
  702. if (krb5_init.addrs[i])
  703. free(krb5_init.addrs[i]);
  704. krb5_init.addrs[i] = NULL;
  705. }
  706. for (i = 0; i <= KRB5_NUM_OF_ADDRS && krb5_d_addrs[i]; i++) {
  707. makestr(&krb5_init.addrs[i],krb5_d_addrs[i]);
  708. }
  709. /* Kerberos 4 */
  710. krb4_init.lifetime = krb4_d_lifetime;
  711. krb4_init.preauth = krb4_d_preauth;
  712. makestr(&krb4_init.instance,krb4_d_instance);
  713. if (!krb4_d_realm || !krb4_d_realm[0]) {/* Set default realm */
  714. char * p;
  715. p = ck_krb4_getrealm();
  716. makestr(&krb4_d_realm,(p && p[0]) ? p : NULL);
  717. }
  718. makestr(&krb4_init.realm,krb4_d_realm);
  719. if (krb4_init.password) {
  720. memset(krb4_init.password,0xFF,strlen(krb4_init.password));
  721. free(krb4_init.password);
  722. krb4_init.password = NULL;
  723. }
  724. if (!krb4_d_principal) { /* Default principal */
  725. /* a Null principal indicates the user should be prompted */
  726. char * p = ck_krb4_getprincipal();
  727. if (!p || !(*p))
  728. p = (char *)uidbuf; /* Principal = user */
  729. makestr(&(krb4_d_principal),(p && p[0]) ? p : NULL);
  730. }
  731. makestr(&(krb4_init.principal),krb4_d_principal);
  732. }
  733. /* D O A U T H -- AUTHENTICATE action routine */
  734. int
  735. doauth(cx) int cx; { /* AUTHENTICATE action routine */
  736. int rc = 0; /* Return code */
  737. #ifdef CK_AUTHENTICATION
  738. #ifdef OS2
  739. if (!ck_security_loaddll()) /* Load various DLLs */
  740. return(rc);
  741. #endif /* OS2 */
  742. if (krb_op.version == 4) { /* Version = 4 */
  743. #ifdef COMMENT
  744. sho_auth(AUTHTYPE_KERBEROS_V4);
  745. #endif /* COMMENT */
  746. if (!ck_krb4_is_installed()) {
  747. printf("?Kerberos 4 is not installed\n");
  748. return(0);
  749. }
  750. switch (krb_action) { /* Perform V4 functions */
  751. case KRB_A_IN: /* INIT */
  752. rc |= !(ck_krb4_initTGT(&krb_op,&krb4_init) < 0);
  753. break;
  754. case KRB_A_DE: /* DESTROY */
  755. rc |= !(ck_krb4_destroy(&krb_op) < 0);
  756. break;
  757. case KRB_A_LC: /* LIST-CREDENTIALS */
  758. rc |= !(ck_krb4_list_creds(&krb_op) < 0);
  759. break;
  760. }
  761. }
  762. if (krb_op.version == 5) { /* V5 functions */
  763. #ifdef COMMENT
  764. sho_auth(AUTHTYPE_KERBEROS_V5);
  765. #endif /* COMMENT */
  766. if (!ck_krb5_is_installed()) {
  767. printf("?Kerberos 5 is not installed\n");
  768. return(0);
  769. }
  770. switch (krb_action) {
  771. case KRB_A_IN: /* INIT */
  772. rc |= !(ck_krb5_initTGT(&krb_op,&krb5_init,
  773. krb5_init.getk4 ? &krb4_init : 0) < 0);
  774. break;
  775. case KRB_A_DE: /* DESTROY */
  776. rc |= !(ck_krb5_destroy(&krb_op) < 0);
  777. break;
  778. case KRB_A_LC: /* LIST-CREDENTIALS */
  779. if (krb_op.version == 0)
  780. printf("\n");
  781. rc |= !(ck_krb5_list_creds(&krb_op,&krb5_lc) < 0);
  782. break;
  783. }
  784. }
  785. #else
  786. #ifndef NOICP
  787. #ifndef NOSHOW
  788. rc = sho_auth(0); /* Show all */
  789. #endif /* NOSHOW */
  790. #endif /* NOICP */
  791. #endif /* CK_AUTHENTICATION */
  792. return(rc);
  793. }
  794. #endif /* CK_KERBEROS */
  795. #ifdef TCPSOCKET
  796. #ifndef OS2
  797. #ifndef NOLISTEN /* For incoming connections */
  798. #ifndef INADDR_ANY
  799. #define INADDR_ANY 0
  800. #endif /* INADDR_ANY */
  801. _PROTOTYP( int ttbufr, ( VOID ) );
  802. _PROTOTYP( int tcpsrv_open, (char *, int *, int, int ) );
  803. static unsigned short tcpsrv_port = 0;
  804. #endif /* NOLISTEN */
  805. #endif /* OS2 */
  806. static char svcbuf[80]; /* TCP service string */
  807. static int svcnum = 0; /* TCP port number */
  808. #endif /* TCPSOCKET */
  809. /*
  810. TCPIPLIB means use separate socket calls for i/o, while on UNIX the
  811. normal file system calls are used for TCP/IP sockets too.
  812. Means "DEC_TCPIP or MULTINET or WINTCP or OS2 or BEBOX" (see ckcnet.h),
  813. */
  814. #ifdef TCPIPLIB
  815. /* For buffered network reads... */
  816. /*
  817. If the buffering code is written right, it shouldn't matter
  818. how long this buffer is.
  819. */
  820. #ifdef OS2
  821. #ifdef NT
  822. #define TTIBUFL 64240 /* 44 * 1460 (MSS) */
  823. #else
  824. #define TTIBUFL 32120 /* 22 * 1460 (MSS) */
  825. #endif /* NT */
  826. #else /* OS2 */
  827. #define TTIBUFL 8191 /* Let's use 8K. */
  828. #endif /* OS2 */
  829. CHAR ttibuf[TTIBUFL+1];
  830. /*
  831. select() is used in preference to alarm()/signal(), but different systems
  832. use different forms of select()...
  833. */
  834. #ifndef NOSELECT /* Option to override BSDSELECT */
  835. #ifdef BELLV10
  836. /*
  837. Note: Although BELLV10 does have TCP/IP support, and does use the unique
  838. form of select() that is evident in this module (and in ckutio.c), it does
  839. not have a sockets library and so we can't build Kermit TCP/IP support for
  840. it. For this, somebody would have to write TCP/IP streams code.
  841. */
  842. #define BELLSELECT
  843. #ifndef FD_SETSIZE
  844. #define FD_SETSIZE 128
  845. #endif /* FD_SETSIZE */
  846. #else
  847. #ifdef WINTCP /* VMS with Wollongong WIN/TCP */
  848. #ifndef OLD_TWG /* TWG 3.2 has only select(read) */
  849. #define BSDSELECT
  850. #endif /* OLD_TWG */
  851. #else
  852. #ifdef CMU_TCPIP /* LIBCMU can do select */
  853. #define BSDSELECT
  854. #else
  855. #ifdef DEC_TCPIP
  856. #define BSDSELECT
  857. #else
  858. #ifdef OS2 /* OS/2 with TCP/IP */
  859. #ifdef NT
  860. #define BSDSELECT
  861. #else /* NT */
  862. #define IBMSELECT
  863. #endif /* NT */
  864. #endif /* OS2 */
  865. #endif /* DEC_TCPIP */
  866. #endif /* CMU_TCPIP */
  867. #endif /* WINTCP */
  868. #endif /* BELLV10 */
  869. #endif /* NOSELECT */
  870. /*
  871. Others (TGV, TCPware, ...) use alarm()/signal(). The BSDSELECT case does not
  872. compile at all; the IBMSELECT case compiles and links but crashes at runtime.
  873. NOTE: If any of these can be converted to select(), they should be for two
  874. reasons: (1) It's a lot faster; (2) certain sockets libraries do not like
  875. their socket_read() calls to be interrupted; subsequent socket_read()'s tend
  876. to fail with EBUSY. This happened in the UCX case before it was converted
  877. to use select().
  878. */
  879. #ifndef OS2
  880. #ifndef VMS
  881. static /* These are used in CKVTIO.C */
  882. #endif /* VMS */ /* And in CKONET.C */
  883. #endif /* OS2 */
  884. int
  885. ttibp = 0,
  886. ttibn = 0;
  887. /*
  888. Read bytes from network into internal buffer ttibuf[].
  889. To be called when input buffer is empty, i.e. when ttibn == 0.
  890. Other network reading routines, like ttinc, ttinl, ttxin, should check the
  891. internal buffer first, and call this routine for a refill if necessary.
  892. Returns -1 on error, 0 if nothing happens. When data is read successfully,
  893. returns number of bytes read, and sets global ttibn to that number and
  894. ttibp (the buffer pointer) to zero.
  895. */
  896. _PROTOTYP( int ttbufr, ( VOID ) );
  897. int
  898. ttbufr() { /* TT Buffer Read */
  899. int count;
  900. if (ttnet != NET_TCPB) /* First make sure current net is */
  901. return(-1); /* TCP/IP; if not, do nothing. */
  902. #ifdef OS2
  903. RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
  904. #endif /* OS2 */
  905. if (ttibn > 0) { /* Our internal buffer is not empty, */
  906. #ifdef OS2
  907. ReleaseTCPIPMutex();
  908. #endif /* OS2 */
  909. return(ttibn); /* so keep using it. */
  910. }
  911. if (ttyfd == -1) { /* No connection, error */
  912. #ifdef OS2
  913. ReleaseTCPIPMutex();
  914. #endif /* OS2 */
  915. return(-2);
  916. }
  917. ttibp = 0; /* Else reset pointer to beginning */
  918. #ifdef WINTCP
  919. count = 512; /* This works for WIN/TCP */
  920. #else
  921. #ifdef DEC_TCPIP
  922. count = 512; /* UCX */
  923. #else
  924. #ifdef OS2
  925. count = TTIBUFL;
  926. #else /* Multinet, etc. */
  927. count = ttchk(); /* Check network input buffer, */
  928. if (ttibn > 0) { /* which can put a char there! */
  929. debug(F111,"ttbufr","ttchk() returns",count);
  930. #ifdef OS2
  931. ReleaseTCPIPMutex();
  932. #endif /* OS2 */
  933. return(ttibn);
  934. }
  935. if (count < 0) { /* Read error - connection closed */
  936. #ifdef OS2
  937. ReleaseTCPIPMutex();
  938. #endif /* OS2 */
  939. return(-2);
  940. }
  941. else if (count > TTIBUFL) /* Too many to read */
  942. count = TTIBUFL;
  943. else if (count == 0) /* None, so force blocking read */
  944. count = 1;
  945. #endif /* OS2 */
  946. #endif /* DEC_TCPIP */
  947. #endif /* WINTCP */
  948. debug(F101,"ttbufr count 1","",count);
  949. #ifdef CK_SSL
  950. if (ssl_active_flag || tls_active_flag) {
  951. int error;
  952. ssl_read:
  953. if (ssl_active_flag)
  954. count = SSL_read(ssl_con, ttibuf, count);
  955. else
  956. count = SSL_read(tls_con, ttibuf, count);
  957. error = SSL_get_error(ssl_active_flag?ssl_con:tls_con,count);
  958. switch (error) {
  959. case SSL_ERROR_NONE:
  960. debug(F111,"ttbufr SSL_ERROR_NONE","count",count);
  961. if (count > 0) {
  962. ttibp = 0; /* Reset buffer pointer. */
  963. ttibn = count;
  964. #ifdef OS2
  965. ReleaseTCPIPMutex();
  966. #endif /* OS2 */
  967. return(ttibn); /* Return buffer count. */
  968. } else if (count < 0) {
  969. #ifdef OS2
  970. ReleaseTCPIPMutex();
  971. #endif /* OS2 */
  972. return(-1);
  973. } else {
  974. netclos();
  975. #ifdef OS2
  976. ReleaseTCPIPMutex();
  977. #endif /* OS2 */
  978. return(-2);
  979. }
  980. case SSL_ERROR_WANT_WRITE:
  981. debug(F100,"ttbufr SSL_ERROR_WANT_WRITE","",0);
  982. #ifdef OS2
  983. ReleaseTCPIPMutex();
  984. #endif /* OS2 */
  985. return(-1);
  986. case SSL_ERROR_WANT_READ:
  987. debug(F100,"ttbufr SSL_ERROR_WANT_READ","",0);
  988. #ifdef OS2
  989. ReleaseTCPIPMutex();
  990. #endif /* OS2 */
  991. return(-1);
  992. case SSL_ERROR_SYSCALL:
  993. if ( count == 0 ) { /* EOF */
  994. netclos();
  995. #ifdef OS2
  996. ReleaseTCPIPMutex();
  997. #endif /* OS2 */
  998. return(-2);
  999. } else {
  1000. int rc = -1;
  1001. #ifdef NT
  1002. int gle = GetLastError();
  1003. debug(F111,"ttbufr SSL_ERROR_SYSCALL",
  1004. "GetLastError()",gle);
  1005. rc = os2socketerror(gle);
  1006. if (rc == -1)
  1007. rc = -2;
  1008. else if ( rc == -2 )
  1009. rc = -1;
  1010. #endif /* NT */
  1011. #ifdef OS2
  1012. ReleaseTCPIPMutex();
  1013. #endif /* OS2 */
  1014. return(rc);
  1015. }
  1016. case SSL_ERROR_WANT_X509_LOOKUP:
  1017. debug(F100,"ttbufr SSL_ERROR_WANT_X509_LOOKUP","",0);
  1018. netclos();
  1019. #ifdef OS2
  1020. ReleaseTCPIPMutex();
  1021. #endif /* OS2 */
  1022. return(-2);
  1023. case SSL_ERROR_SSL:
  1024. if (bio_err!=NULL) {
  1025. int len;
  1026. extern char ssl_err[];
  1027. BIO_printf(bio_err,"ttbufr SSL_ERROR_SSL\n");
  1028. ERR_print_errors(bio_err);
  1029. len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
  1030. ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
  1031. debug(F110,"ttbufr SSL_ERROR_SSL",ssl_err,0);
  1032. if (ssl_debug_flag)
  1033. printf(ssl_err);
  1034. } else if (ssl_debug_flag) {
  1035. debug(F100,"ttbufr SSL_ERROR_SSL","",0);
  1036. fflush(stderr);
  1037. fprintf(stderr,"ttbufr SSL_ERROR_SSL\n");
  1038. ERR_print_errors_fp(stderr);
  1039. }
  1040. #ifdef COMMENT
  1041. netclos();
  1042. #endif /* COMMENT */
  1043. #ifdef OS2
  1044. ReleaseTCPIPMutex();
  1045. #endif /* OS2 */
  1046. return(-2);
  1047. case SSL_ERROR_ZERO_RETURN:
  1048. debug(F100,"ttbufr SSL_ERROR_ZERO_RETURN","",0);
  1049. netclos();
  1050. #ifdef OS2
  1051. ReleaseTCPIPMutex();
  1052. #endif /* OS2 */
  1053. return(-2);
  1054. default:
  1055. debug(F100,"ttbufr SSL_ERROR_?????","",0);
  1056. netclos();
  1057. #ifdef OS2
  1058. ReleaseTCPIPMutex();
  1059. #endif /* OS2 */
  1060. return(-2);
  1061. }
  1062. }
  1063. #endif /* CK_SSL */
  1064. #ifdef COMMENT
  1065. /*
  1066. This is for nonblocking reads, which we don't do any more. This code didn't
  1067. work anyway, in the sense that a broken connection was never sensed.
  1068. */
  1069. if ((count = socket_read(ttyfd,&ttibuf[ttibp+ttibn],count)) < 1) {
  1070. if (count == -1 && socket_errno == EWOULDBLOCK) {
  1071. debug(F100,"ttbufr finds nothing","",0);
  1072. #ifdef OS2
  1073. ReleaseTCPIPMutex();
  1074. #endif /* OS2 */
  1075. return(0);
  1076. } else {
  1077. debug(F101,"ttbufr socket_read error","",socket_errno);
  1078. #ifdef OS2
  1079. ReleaseTCPIPMutex();
  1080. #endif /* OS2 */
  1081. return(-1);
  1082. }
  1083. } else if (count == 0) {
  1084. debug(F100,"ttbufr socket eof","",0);
  1085. #ifdef OS2
  1086. ReleaseTCPIPMutex();
  1087. #endif /* OS2 */
  1088. return(-1);
  1089. }
  1090. #else /* COMMENT */
  1091. /* This is for blocking reads */
  1092. #ifndef VMS
  1093. #ifdef SO_OOBINLINE
  1094. {
  1095. int outofband = 0;
  1096. #ifdef BELLSELECT
  1097. if (select(128, NULL, NULL, efds, 0) > 0 && FD_ISSET(ttyfd, efds))
  1098. outofband = 1;
  1099. #else
  1100. #ifdef BSDSELECT
  1101. fd_set efds;
  1102. struct timeval tv;
  1103. FD_ZERO(&efds);
  1104. FD_SET(ttyfd, &efds);
  1105. tv.tv_sec = tv.tv_usec = 0L;
  1106. debug(F100,"Out-of-Band BSDSELECT","",0);
  1107. #ifdef NT
  1108. WSASafeToCancel = 1;
  1109. #endif /* NT */
  1110. if (select(FD_SETSIZE, NULL, NULL, &efds, &tv) > 0 &&
  1111. FD_ISSET(ttyfd, &efds))
  1112. outofband = 1;
  1113. #ifdef NT
  1114. WSASafeToCancel = 0;
  1115. #endif /* NT */
  1116. #else /* !BSDSELECT */
  1117. #ifdef IBMSELECT
  1118. /* Is used by OS/2 ... */
  1119. /* ... and it came in handy! For our TCP/IP layer, it avoids all the fd_set */
  1120. /* and timeval stuff since this is the only place where it is used. */
  1121. int socket = ttyfd;
  1122. debug(F100,"Out-of-Band IBMSELECT","",0);
  1123. if ((select(&socket, 0, 0, 1, 0L) == 1) && (socket == ttyfd))
  1124. outofband = 1;
  1125. #else /* !IBMSELECT */
  1126. /*
  1127. If we can't use select(), then we use the regular alarm()/signal()
  1128. timeout mechanism.
  1129. */
  1130. debug(F101,"Out-of-Band data not supported","",0);
  1131. outofband = 0;
  1132. #endif /* IBMSELECT */
  1133. #endif /* BSDSELECT */
  1134. #endif /* BELLSELECT */
  1135. if (outofband) {
  1136. /* Get the Urgent Data */
  1137. /* if OOBINLINE is disabled this should be only a single byte */
  1138. /* MS Winsock has a bug in Windows 95. Extra bytes are delivered */
  1139. /* That were never sent. */
  1140. #ifdef OS2
  1141. RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
  1142. #endif /* OS2 */
  1143. count = socket_recv(ttyfd,&ttibuf[ttibp+ttibn],count,MSG_OOB);
  1144. #ifdef OS2
  1145. ReleaseTCPIPMutex();
  1146. #endif /* OS2 */
  1147. if (count <= 0) {
  1148. int s_errno = socket_errno;
  1149. debug(F101, "ttbufr socket_recv MSG_OOB","",count);
  1150. debug(F101, "ttbufr socket_errno","",s_errno);
  1151. #ifdef OS2ONLY
  1152. if (count < 0 && (s_errno == 0 || s_errno == 23)) {
  1153. /* These appear in OS/2 - don't know why */
  1154. /* ignore it and read as normal data */
  1155. /* and break, then we will attempt to read */
  1156. /* the port using normal read() techniques */
  1157. debug(F100,"ttbufr handing as in-band data","",0);
  1158. count = 1;
  1159. } else {
  1160. netclos(); /* *** *** */
  1161. #ifdef OS2
  1162. ReleaseTCPIPMutex();
  1163. #endif /* OS2 */
  1164. return(-2);
  1165. }
  1166. #else /* OS2ONLY */
  1167. netclos(); /* *** *** */
  1168. #ifdef OS2
  1169. ReleaseTCPIPMutex();
  1170. #endif /* OS2 */
  1171. return(-2);
  1172. #endif /* OS2ONLY */
  1173. } else { /* we got out-of-band data */
  1174. ckhexdump("ttbufr out-of-band chars",&ttibuf[ttibp+ttibn],count);
  1175. #ifdef BETADEBUG
  1176. bleep(BP_NOTE);
  1177. #endif /* BETADEBUG */
  1178. #ifdef RLOGCODE /* blah */
  1179. if (ttnproto == NP_RLOGIN ||
  1180. ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN ||
  1181. ((ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN) &&
  1182. !rlog_inband)
  1183. )
  1184. {
  1185. /*
  1186. When urgent data is read with MSG_OOB and not OOBINLINE
  1187. then urgent data and normal data are not mixed. So
  1188. treat the entire buffer as urgent data.
  1189. */
  1190. rlog_oob(&ttibuf[ttibp+ttibn], count);
  1191. #ifdef OS2
  1192. ReleaseTCPIPMutex();
  1193. #endif /* OS2 */
  1194. return ttbufr();
  1195. } else
  1196. #endif /* RLOGCODE */ /* blah */
  1197. #ifdef COMMENT
  1198. /*
  1199. I haven't written this yet, nor do I know what it should do
  1200. */
  1201. if (ttnproto == NP_TELNET) {
  1202. tn_oob();
  1203. #ifdef OS2
  1204. ReleaseTCPIPMutex();
  1205. #endif /* OS2 */
  1206. return 0;
  1207. } else
  1208. #endif /* COMMENT */
  1209. {
  1210. /* For any protocols we don't have a special out-of-band */
  1211. /* handler for, just put the bytes in the normal buffer */
  1212. /* and return */
  1213. ttibp += 0; /* Reset buffer pointer. */
  1214. ttibn += count;
  1215. #ifdef DEBUG
  1216. /* Got some bytes. */
  1217. debug(F101,"ttbufr count 2","",count);
  1218. if (count > 0)
  1219. ttibuf[ttibp+ttibn] = '\0';
  1220. debug(F111,"ttbufr ttibuf",ttibuf,ttibp);
  1221. #endif /* DEBUG */
  1222. #ifdef OS2
  1223. ReleaseTCPIPMutex();
  1224. #endif /* OS2 */
  1225. return(ttibn); /* Return buffer count. */
  1226. }
  1227. }
  1228. }
  1229. }
  1230. #endif /* SO_OOBINLINE */
  1231. #endif /* VMS */
  1232. count = socket_read(ttyfd,&ttibuf[ttibp+ttibn],count);
  1233. if (count <= 0) {
  1234. int s_errno = socket_errno;
  1235. debug(F101,"ttbufr socket_read","",count);
  1236. debug(F101,"ttbufr socket_errno","",s_errno);
  1237. #ifdef OS2
  1238. if (count == 0 || os2socketerror(s_errno) < 0) {
  1239. netclos();
  1240. ReleaseTCPIPMutex();
  1241. return(-2);
  1242. }
  1243. ReleaseTCPIPMutex();
  1244. return(-1);
  1245. #else /* OS2 */
  1246. netclos(); /* *** *** */
  1247. return(-2);
  1248. #endif /* OS2 */
  1249. }
  1250. #endif /* COMMENT */ /* (blocking vs nonblock reads...) */
  1251. else {
  1252. ttibp = 0; /* Reset buffer pointer. */
  1253. ttibn += count;
  1254. #ifdef DEBUG
  1255. debug(F101,"ttbufr count 2","",count); /* Got some bytes. */
  1256. if (count > 0)
  1257. ttibuf[ttibp+ttibn] = '\0';
  1258. debug(F111,"ttbufr ttibuf",&ttibuf[ttibp],ttibn);
  1259. #endif /* DEBUG */
  1260. #ifdef OS2
  1261. ReleaseTCPIPMutex();
  1262. #endif /* OS2 */
  1263. return(ttibn); /* Return buffer count. */
  1264. }
  1265. }
  1266. #endif /* TCPIPLIB */
  1267. #ifndef IBMSELECT
  1268. #ifndef BELLSELECT
  1269. #ifndef BSDSELECT /* Non-TCPIPLIB case */
  1270. #ifdef SELECT
  1271. #define BSDSELECT
  1272. #endif /* SELECT */
  1273. #endif /* BSDSELECT */
  1274. #endif /* BELLSELECT */
  1275. #endif /* IBMSELECT */
  1276. #define TELNET_PORT 23 /* Should do lookup, but it won't change */
  1277. #define RLOGIN_PORT 513
  1278. #define KERMIT_PORT 1649
  1279. #define KLOGIN_PORT 543
  1280. #define EKLOGIN_PORT 2105
  1281. #ifndef NONET
  1282. /*
  1283. C-Kermit network open/close functions for BSD-sockets.
  1284. Much of this code shared by SunLink X.25, which also uses the socket library.
  1285. */
  1286. /* N E T O P N -- Open a network connection. */
  1287. /*
  1288. Call with:
  1289. name of host (or host:service),
  1290. lcl - local-mode flag to be set if this function succeeds,
  1291. network type - value defined in ckunet.h.
  1292. */
  1293. #ifdef TCPSOCKET
  1294. struct hostent *
  1295. #ifdef CK_ANSIC
  1296. ck_copyhostent(struct hostent * h)
  1297. #else /* CK_ANSIC */
  1298. ck_copyhostent(h) struct hostent * h;
  1299. #endif /* CK_ANSIC */
  1300. {
  1301. /*
  1302. * The hostent structure is dynamic in nature.
  1303. * struct hostent {
  1304. * char * h_name;
  1305. * char * * h_aliases;
  1306. * short h_addrtype;
  1307. * short h_length;
  1308. * char * * h_addr_list;
  1309. * #define h_addr h_addr_list[0]
  1310. */
  1311. #define HOSTENTCNT 5
  1312. static struct hostent hosts[HOSTENTCNT] = {{NULL,NULL,0,0,NULL},
  1313. {NULL,NULL,0,0,NULL},
  1314. {NULL,NULL,0,0,NULL},
  1315. {NULL,NULL,0,0,NULL},
  1316. {NULL,NULL,0,0,NULL}};
  1317. static int next = 0;
  1318. int i,cnt;
  1319. char ** pp;
  1320. if ( h == NULL )
  1321. return(NULL);
  1322. if (next == HOSTENTCNT)
  1323. next = 0;
  1324. if ( hosts[next].h_name ) {
  1325. free(hosts[next].h_name);
  1326. hosts[next].h_name = NULL;
  1327. }
  1328. if ( hosts[next].h_aliases ) {
  1329. pp = hosts[next].h_aliases;
  1330. while ( *pp ) {
  1331. free(*pp);
  1332. pp++;
  1333. }
  1334. free(hosts[next].h_aliases);
  1335. }
  1336. #ifdef HADDRLIST
  1337. if ( hosts[next].h_addr_list ) {
  1338. pp = hosts[next].h_addr_list;
  1339. while ( *pp ) {
  1340. free(*pp);
  1341. pp++;
  1342. }
  1343. free(hosts[next].h_addr_list);
  1344. }
  1345. #endif /* HADDRLIST */
  1346. makestr(&hosts[next].h_name,h->h_name);
  1347. if (h->h_aliases) {
  1348. for ( cnt=0,pp=h->h_aliases; pp && *pp; pp++,cnt++) ;
  1349. /* The following can give warnings in non-ANSI builds */
  1350. hosts[next].h_aliases = (char **) malloc(sizeof(char *) * (cnt+1));
  1351. for ( i=0; i<cnt; i++) {
  1352. hosts[next].h_aliases[i] = NULL;
  1353. makestr(&hosts[next].h_aliases[i],h->h_aliases[i]);
  1354. }
  1355. hosts[next].h_aliases[i] = NULL;
  1356. } else
  1357. hosts[next].h_aliases = NULL;
  1358. hosts[next].h_addrtype = h->h_addrtype;
  1359. hosts[next].h_length = h->h_length;
  1360. #ifdef HADDRLIST
  1361. #ifdef h_addr
  1362. if (h->h_addr_list) {
  1363. for ( cnt=0,pp=h->h_addr_list; pp && *pp; pp++,cnt++) ;
  1364. /* The following can give warnings non-ANSI builds */
  1365. hosts[next].h_addr_list = (char **) malloc(sizeof(char *) * (cnt+1));
  1366. for ( i=0; i<cnt; i++) {
  1367. hosts[next].h_addr_list[i] = malloc(h->h_length);
  1368. bcopy(h->h_addr_list[i],hosts[next].h_addr_list[i],h->h_length);
  1369. }
  1370. hosts[next].h_addr_list[i] = NULL;
  1371. } else
  1372. hosts[next].h_addr_list = NULL;
  1373. #else
  1374. bcopy(h->h_addr, &hosts[next].h_addr, h->h_length);
  1375. #endif /* h_addr */
  1376. #else /* HADDRLIST */
  1377. bcopy(h->h_addr, &hosts[next].h_addr, h->h_length);
  1378. #endif /* HADDRLIST */
  1379. return(&hosts[next++]);
  1380. }
  1381. #ifdef EXCELAN
  1382. /*
  1383. Most other BSD sockets implementations define these in header files
  1384. and libraries.
  1385. */
  1386. struct servent {
  1387. unsigned short s_port;
  1388. };
  1389. struct hostent {
  1390. short h_addrtype;
  1391. struct in_addr h_addr;
  1392. int h_length;
  1393. };
  1394. struct servent *
  1395. getservbyname(service, connection) char *service,*connection; {
  1396. static struct servent servrec;
  1397. int port;
  1398. port = 0;
  1399. if (strcmp(service, "telnet") == 0) port = 23;
  1400. else if (strcmp(service, "smtp") == 0) port = 25;
  1401. else port = atoi(service);
  1402. debug(F101,"getservbyname return port ","",port);
  1403. if (port > 0) {
  1404. servrec.s_port = htons(port);
  1405. return(&servrec);
  1406. }
  1407. return((struct servent *) NULL);
  1408. }
  1409. struct hostent *
  1410. gethostbyname(hostname) char *hostname; {
  1411. return((struct hostent *) NULL);
  1412. }
  1413. unsigned long
  1414. inet_addr(name) char *name; {
  1415. unsigned long addr;
  1416. addr = rhost(&name);
  1417. debug(F111,"inet_addr ",name,(int)addr);
  1418. return(addr);
  1419. }
  1420. char *
  1421. inet_ntoa(in) struct in_addr in; {
  1422. static char name[80];
  1423. ckmakxmsg(name, ckuitoa(in.s_net),".",ckuitoa(in.s_host),".",
  1424. ckuitoa(in.s_lh),".", ckuitoa(in.s_impno));
  1425. return(name);
  1426. }
  1427. #else
  1428. #ifdef DEC_TCPIP /* UCX */
  1429. int ucx_port_bug = 0; /* Explained below */
  1430. #ifdef OLDIP /* Very old VAXC or GCC */
  1431. /*
  1432. Note that my oldest VAX C (V3.1-051) does not need (or want) OLDIP,
  1433. hence the "Very old" in the comment - SMS, 2010/03/15.
  1434. */
  1435. #define getservbyname my_getservbyname
  1436. #ifdef CK_ANSIC
  1437. globalref int (*C$$GA_UCX_GETSERVBYNAME)();
  1438. extern void C$$TRANSLATE();
  1439. extern void C$$SOCK_TRANSLATE();
  1440. #else
  1441. globalref int (*C$$GA_UCX_GETSERVBYNAME)();
  1442. extern VOID C$$TRANSLATE();
  1443. extern VOID C$$SOCK_TRANSLATE();
  1444. #endif /* CK_ANSIC */
  1445. struct servent *
  1446. my_getservbyname (service, proto) char *service, *proto; {
  1447. static struct servent sent;
  1448. struct iosb {
  1449. union {
  1450. unsigned long status;
  1451. unsigned short st[2];
  1452. } sb;
  1453. unsigned long spare;
  1454. } s;
  1455. struct {
  1456. struct iosb *s;
  1457. char *serv;
  1458. char *prot;
  1459. } par;
  1460. unsigned long e;
  1461. char sbuf[30], pbuf[30];
  1462. char *p;
  1463. debug(F111,"UCX getservbyname",service,(int)C$$GA_UCX_GETSERVBYNAME);
  1464. p = sbuf;
  1465. ckstrncpy(p, service, 29);
  1466. while (*p = toupper(*p), *p++) {}
  1467. p = pbuf;
  1468. ckstrncpy(p, proto, 29);
  1469. while (*p = toupper(*p), *p++) {}
  1470. par.s = &s;
  1471. par.serv = "";
  1472. par.prot = "";
  1473. /* reset file pointer or something like that!?!? */
  1474. e = (*C$$GA_UCX_GETSERVBYNAME)(&par, &sent, par.s);
  1475. par.serv = sbuf;
  1476. par.prot = pbuf; /* that is don't care */
  1477. e = (*C$$GA_UCX_GETSERVBYNAME)(&par, &sent, par.s);
  1478. if ((long)e == -1L)
  1479. return NULL;
  1480. if ((e & 1) == 0L) {
  1481. C$$TRANSLATE(e);
  1482. return NULL;
  1483. }
  1484. if ((s.sb.st[0] & 1) == 0) {
  1485. C$$SOCK_TRANSLATE(&s.sb.st[0]);
  1486. return NULL;
  1487. }
  1488. /*
  1489. sent.s_port is supposed to be returned by UCX in network byte order.
  1490. However, UCX 2.0 through 2.0C did not do this; 2.0D and later do it.
  1491. But there is no way of knowing which UCX version, so we have a user-settable
  1492. runtime variable. Note: UCX 2.0 was only for the VAX.
  1493. */
  1494. debug(F101,"UCX getservbyname port","",sent.s_port);
  1495. debug(F101,"UCX getservbyname ntohs(port)","",ntohs(sent.s_port));
  1496. if (ucx_port_bug) {
  1497. sent.s_port = htons(sent.s_port);
  1498. debug(F100,"UCX-PORT-BUG ON: swapping bytes","",0);
  1499. debug(F101,"UCX swapped port","",sent.s_port);
  1500. debug(F101,"UCX swapped ntohs(port)","",ntohs(sent.s_port));
  1501. }
  1502. return &sent;
  1503. }
  1504. #endif /* def OLDIP */
  1505. #endif /* DEC_TCPIP */
  1506. #endif /* EXCELAN */
  1507. int
  1508. gettcpport() {
  1509. return(svcnum);
  1510. }
  1511. #endif /* TCPSOCKET */
  1512. #ifndef NOTCPOPTS
  1513. #ifndef datageneral
  1514. int
  1515. ck_linger(sock, onoff, timo) int sock; int onoff; int timo; {
  1516. /*
  1517. The following, from William Bader, turns off the socket linger parameter,
  1518. which makes a close() block until all data is sent. "I don't think that
  1519. disabling linger can ever cause kermit to lose data, but you telnet to a
  1520. flaky server (or to our modem server when the modem is in use), disabling
  1521. linger prevents kermit from hanging on the close if you try to exit."
  1522. Modified by Jeff Altman to be generally useful.
  1523. */
  1524. #ifdef SOL_SOCKET
  1525. #ifdef SO_LINGER
  1526. struct linger set_linger_opt;
  1527. struct linger get_linger_opt;
  1528. SOCKOPT_T x;
  1529. #ifdef IKSD
  1530. if (!inserver)
  1531. #endif /* IKSD */
  1532. if (sock == -1 ||
  1533. nettype != NET_TCPA && nettype != NET_TCPB &&
  1534. nettype != NET_SSH || ttmdm >= 0) {
  1535. tcp_linger = onoff;
  1536. tcp_linger_tmo = timo;
  1537. return(1);
  1538. }
  1539. x = sizeof(get_linger_opt);
  1540. if (getsockopt(sock, SOL_SOCKET, SO_LINGER,
  1541. (char *)&get_linger_opt, &x)) {
  1542. debug(F111,"TCP ck_linger can't get SO_LINGER",ck_errstr(),errno);
  1543. } else if (x != sizeof(get_linger_opt)) {
  1544. #ifdef OS2
  1545. struct _linger16 {
  1546. short s_linger;
  1547. short s_onoff;
  1548. } get_linger_opt16, set_linger_opt16;
  1549. if ( x == sizeof(get_linger_opt16) ) {
  1550. debug(F111,"TCP setlinger warning: SO_LINGER","len is 16-bit",x);
  1551. if (getsockopt(sock,
  1552. SOL_SOCKET, SO_LINGER,
  1553. (char *)&get_linger_opt16, &x)
  1554. ) {
  1555. debug(F111,
  1556. "TCP ck_linger can't get SO_LINGER",ck_errstr(),errno);
  1557. } else if (get_linger_opt16.s_onoff != onoff ||
  1558. get_linger_opt16.s_linger != timo)
  1559. {
  1560. set_linger_opt16.s_onoff = onoff;
  1561. set_linger_opt16.s_linger = timo;
  1562. if (setsockopt(sock,
  1563. SOL_SOCKET,
  1564. SO_LINGER,
  1565. (char *)&set_linger_opt16,
  1566. sizeof(set_linger_opt16))
  1567. ) {
  1568. debug(F111,
  1569. "TCP ck_linger can't set SO_LINGER",
  1570. ck_errstr(),
  1571. errno
  1572. );
  1573. tcp_linger = get_linger_opt16.s_onoff;
  1574. tcp_linger_tmo = get_linger_opt16.s_linger;
  1575. } else {
  1576. debug(F101,
  1577. "TCP ck_linger new SO_LINGER","",
  1578. set_linger_opt16.s_onoff);
  1579. tcp_linger = set_linger_opt16.s_onoff;
  1580. tcp_linger_tmo = set_linger_opt16.s_linger;
  1581. return 1;
  1582. }
  1583. } else {
  1584. debug(F101,"TCP ck_linger SO_LINGER unchanged","",
  1585. get_linger_opt16.s_onoff);
  1586. tcp_linger = get_linger_opt16.s_onoff;
  1587. tcp_linger_tmo = get_linger_opt16.s_linger;
  1588. return 1;
  1589. }
  1590. return(0);
  1591. }
  1592. #endif /* OS2 */
  1593. debug(F111,"TCP ck_linger error: SO_LINGER","len",x);
  1594. debug(F111,"TCP ck_linger SO_LINGER",
  1595. "expected len",sizeof(get_linger_opt));
  1596. debug(F111,"TCP ck_linger SO_LINGER","linger_opt.l_onoff",
  1597. get_linger_opt.l_onoff);
  1598. debug(F111,"TCP linger SO_LINGER","linger_opt.l_linger",
  1599. get_linger_opt.l_linger);
  1600. } else if (get_linger_opt.l_onoff != onoff ||
  1601. get_linger_opt.l_linger != timo) {
  1602. set_linger_opt.l_onoff = onoff;
  1603. set_linger_opt.l_linger = timo;
  1604. if (setsockopt(sock,
  1605. SOL_SOCKET,
  1606. SO_LINGER,
  1607. (char *)&set_linger_opt,
  1608. sizeof(set_linger_opt))) {
  1609. debug(F111,"TCP ck_linger can't set SO_LINGER",ck_errstr(),errno);
  1610. tcp_linger = get_linger_opt.l_onoff;
  1611. tcp_linger_tmo = get_linger_opt.l_linger;
  1612. } else {
  1613. debug(F101,
  1614. "TCP ck_linger new SO_LINGER",
  1615. "",
  1616. set_linger_opt.l_onoff
  1617. );
  1618. tcp_linger = set_linger_opt.l_onoff;
  1619. tcp_linger_tmo = set_linger_opt.l_linger;
  1620. return 1;
  1621. }
  1622. } else {
  1623. debug(F101,"TCP ck_linger SO_LINGER unchanged","",
  1624. get_linger_opt.l_onoff);
  1625. tcp_linger = get_linger_opt.l_onoff;
  1626. tcp_linger_tmo = get_linger_opt.l_linger;
  1627. return 1;
  1628. }
  1629. #else
  1630. debug(F100,"TCP ck_linger SO_LINGER not defined","",0);
  1631. #endif /* SO_LINGER */
  1632. #else
  1633. debug(F100,"TCP ck_linger SO_SOCKET not defined","",0);
  1634. #endif /* SOL_SOCKET */
  1635. return(0);
  1636. }
  1637. int
  1638. sendbuf(sock,size) int sock; int size; {
  1639. /*
  1640. The following, from William Bader, allows changing of socket buffer sizes,
  1641. in case that might affect performance.
  1642. Modified by Jeff Altman to be generally useful.
  1643. */
  1644. #ifdef SOL_SOCKET
  1645. #ifdef SO_SNDBUF
  1646. int i, j;
  1647. SOCKOPT_T x;
  1648. #ifdef IKSD
  1649. if (!inserver)
  1650. #endif /* IKSD */
  1651. if (sock == -1 ||
  1652. nettype != NET_TCPA && nettype != NET_TCPB && nettype != NET_SSH
  1653. || ttmdm >= 0) {
  1654. tcp_sendbuf = size;
  1655. return 1;
  1656. }
  1657. x = sizeof(i);
  1658. if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&i, &x)) {
  1659. debug(F111,"TCP sendbuf can't get SO_SNDBUF",ck_errstr(),errno);
  1660. } else if (x != sizeof(i)) {
  1661. #ifdef OS2
  1662. short i16,j16;
  1663. if (x == sizeof(i16)) {
  1664. debug(F111,"TCP sendbuf warning: SO_SNDBUF","len is 16-bit",x);
  1665. if (getsockopt(sock,
  1666. SOL_SOCKET, SO_SNDBUF,
  1667. (char *)&i16, &x)
  1668. ) {
  1669. debug(F111,"TCP sendbuf can't get SO_SNDBUF",
  1670. ck_errstr(),errno);
  1671. } else if (size <= 0) {
  1672. tcp_sendbuf = i16;
  1673. debug(F101,"TCP sendbuf SO_SNDBUF retrieved","",i16);
  1674. return 1;
  1675. } else if (i16 != size) {
  1676. j16 = size;
  1677. if (setsockopt(sock,
  1678. SOL_SOCKET,
  1679. SO_SNDBUF,
  1680. (char *)&j16,
  1681. sizeof(j16))
  1682. ) {
  1683. debug(F111,"TCP sendbuf can't set SO_SNDBUF",
  1684. ck_errstr(),errno);
  1685. } else {
  1686. debug(F101,"TCP sendbuf old SO_SNDBUF","",i16);
  1687. debug(F101,"TCP sendbuf new SO_SNDBUF","",j16);
  1688. tcp_sendbuf = size;
  1689. return 1;
  1690. }
  1691. } else {
  1692. debug(F101,"TCP sendbuf SO_SNDBUF unchanged","",i16);
  1693. tcp_sendbuf = size;
  1694. return 1;
  1695. }
  1696. return(0);
  1697. }
  1698. #endif /* OS2 */
  1699. debug(F111,"TCP sendbuf error: SO_SNDBUF","len",x);
  1700. debug(F111,"TCP sendbuf SO_SNDBUF","expected len",sizeof(i));
  1701. debug(F111,"TCP sendbuf SO_SNDBUF","i",i);
  1702. } else if (size <= 0) {
  1703. tcp_sendbuf = i;
  1704. debug(F101,"TCP sendbuf SO_SNDBUF retrieved","",i);
  1705. return 1;
  1706. } else if (i != size) {
  1707. j = size;
  1708. if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&j, sizeof(j))) {
  1709. debug(F111,"TCP sendbuf can't set SO_SNDBUF",ck_errstr(),errno);
  1710. tcp_sendbuf = i;
  1711. } else {
  1712. debug(F101,"TCP sendbuf old SO_SNDBUF","",i);
  1713. debug(F101,"TCP sendbuf new SO_SNDBUF","",j);
  1714. tcp_sendbuf = size;
  1715. return 1;
  1716. }
  1717. } else {
  1718. debug(F101,"TCP sendbuf SO_SNDBUF unchanged","",i);
  1719. tcp_sendbuf = size;
  1720. return 1;
  1721. }
  1722. #else
  1723. debug(F100,"TCP sendbuf SO_SNDBUF not defined","",0);
  1724. #endif /* SO_SNDBUF */
  1725. #else
  1726. debug(F100,"TCP sendbuf SO_SOCKET not defined","",0);
  1727. #endif /* SOL_SOCKET */
  1728. return(0);
  1729. }
  1730. int
  1731. recvbuf(sock,size) int sock; int size; {
  1732. /*
  1733. The following, from William Bader, allows changing of socket buffer sizes,
  1734. in case that might affect performance.
  1735. Modified by Jeff Altman to be generally useful.
  1736. */
  1737. #ifdef SOL_SOCKET
  1738. #ifdef SO_RCVBUF
  1739. int i, j;
  1740. SOCKOPT_T x;
  1741. #ifdef IKSD
  1742. if (!inserver)
  1743. #endif /* IKSD */
  1744. if (sock == -1 ||
  1745. nettype != NET_TCPA && nettype != NET_TCPB &&
  1746. nettype != NET_SSH || ttmdm >= 0) {
  1747. tcp_recvbuf = size;
  1748. return(1);
  1749. }
  1750. x = sizeof(i);
  1751. if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&i, &x)) {
  1752. debug(F111,"TCP recvbuf can't get SO_RCVBUF",ck_errstr(),errno);
  1753. } else if (x != sizeof(i)) {
  1754. #ifdef OS2
  1755. short i16,j16;
  1756. if ( x == sizeof(i16) ) {
  1757. debug(F111,"TCP recvbuf warning: SO_RCVBUF","len is 16-bit",x);
  1758. if (getsockopt(sock,
  1759. SOL_SOCKET, SO_RCVBUF,
  1760. (char *)&i16, &x)
  1761. ) {
  1762. debug(F111,"TCP recvbuf can't get SO_RCVBUF",
  1763. ck_errstr(),errno);
  1764. } else if (size <= 0) {
  1765. tcp_recvbuf = i16;
  1766. debug(F101,"TCP recvbuf SO_RCVBUF retrieved","",i16);
  1767. return 1;
  1768. } else if (i16 != size) {
  1769. j16 = size;
  1770. if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&j16,
  1771. sizeof(j16))) {
  1772. debug(F111,"TCP recvbuf can' set SO_RCVBUF",
  1773. ck_errstr(),errno);
  1774. } else {
  1775. debug(F101,"TCP recvbuf old SO_RCVBUF","",i16);
  1776. debug(F101,"TCP recvbuf new SO_RCVBUF","",j16);
  1777. tcp_recvbuf = size;
  1778. return 1;
  1779. }
  1780. } else {
  1781. debug(F101,"TCP recvbuf SO_RCVBUF unchanged","",i16);
  1782. tcp_recvbuf = size;
  1783. return 1;
  1784. }
  1785. return(0);
  1786. }
  1787. #endif /* OS2 */
  1788. debug(F111,"TCP recvbuf error: SO_RCVBUF","len",x);
  1789. debug(F111,"TCP recvbuf SO_RCVBUF","expected len",sizeof(i));
  1790. debug(F111,"TCP recvbuf SO_RCVBUF","i",i);
  1791. } else if (size <= 0) {
  1792. tcp_recvbuf = i;
  1793. debug(F101,"TCP recvbuf SO_RCVBUF retrieved","",i);
  1794. return 1;
  1795. } else if (i != size) {
  1796. j = size;
  1797. if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&j, sizeof(j))) {
  1798. debug(F111,"TCP recvbuf can't set SO_RCVBUF",ck_errstr(),errno);
  1799. tcp_recvbuf = i;
  1800. } else {
  1801. debug(F101,"TCP recvbuf old SO_RCVBUF","",i);
  1802. debug(F101,"TCP recvbuf new SO_RCVBUF","",j);
  1803. tcp_recvbuf = size;
  1804. return 1;
  1805. }
  1806. } else {
  1807. debug(F101,"TCP recvbuf SO_RCVBUF unchanged","",i);
  1808. tcp_recvbuf = size;
  1809. return 1;
  1810. }
  1811. #else
  1812. debug(F100,"TCP recvbuf SO_RCVBUF not defined","",0);
  1813. #endif /* SO_RCVBUF */
  1814. #else
  1815. debug(F100,"TCP recvbuf SO_SOCKET not defined","",0);
  1816. #endif /* SOL_SOCKET */
  1817. return 0;
  1818. }
  1819. int
  1820. keepalive(sock,onoff) int sock; int onoff; {
  1821. #ifdef SOL_SOCKET
  1822. #ifdef SO_KEEPALIVE
  1823. int get_keepalive_opt;
  1824. int set_keepalive_opt;
  1825. SOCKOPT_T x;
  1826. debug(F111,"TCP keepalive","sock",sock);
  1827. debug(F111,"TCP keepalive","nettype",nettype);
  1828. debug(F111,"TCP keepalive","ttmdm",ttmdm);
  1829. #ifdef IKSD
  1830. if (!inserver)
  1831. #endif /* IKSD */
  1832. if (sock == -1 ||
  1833. nettype != NET_TCPA && nettype != NET_TCPB && nettype != NET_SSH
  1834. || ttmdm >= 0) {
  1835. tcp_keepalive = onoff;
  1836. return 1;
  1837. }
  1838. x = sizeof(get_keepalive_opt);
  1839. if (getsockopt(sock,
  1840. SOL_SOCKET, SO_KEEPALIVE, (char *)&get_keepalive_opt, &x)) {
  1841. debug(F111,"TCP keepalive can't get SO_KEEPALIVE",ck_errstr(),errno);
  1842. } else if (x != sizeof(get_keepalive_opt)) {
  1843. #ifdef OS2
  1844. short get_keepalive_opt16;
  1845. short set_keepalive_opt16;
  1846. if (x == sizeof(get_keepalive_opt16)) {
  1847. debug(F111,"TCP keepalive warning: SO_KEEPALIVE",
  1848. "len is 16-bit",x);
  1849. if (getsockopt(sock,
  1850. SOL_SOCKET, SO_KEEPALIVE,
  1851. (char *)&get_keepalive_opt16, &x)
  1852. ) {
  1853. debug(F111,
  1854. "TCP keepalive can't get SO_KEEPALIVE",
  1855. ck_errstr(),
  1856. errno
  1857. );
  1858. } else if (get_keepalive_opt16 != onoff) {
  1859. set_keepalive_opt16 = onoff;
  1860. if (setsockopt(sock,
  1861. SOL_SOCKET,
  1862. SO_KEEPALIVE,
  1863. (char *)&set_keepalive_opt16,
  1864. sizeof(set_keepalive_opt16))
  1865. ) {
  1866. debug(F111,
  1867. "TCP keepalive can't clear SO_KEEPALIVE",
  1868. ck_errstr(),
  1869. errno
  1870. );
  1871. tcp_keepalive = get_keepalive_opt16;
  1872. } else {
  1873. debug(F101,
  1874. "TCP keepalive new SO_KEEPALIVE","",
  1875. set_keepalive_opt16);
  1876. tcp_keepalive = set_keepalive_opt16;
  1877. return 1;
  1878. }
  1879. } else {
  1880. debug(F101,"TCP keepalive SO_KEEPALIVE unchanged","",
  1881. get_keepalive_opt16);
  1882. tcp_keepalive = onoff;
  1883. return 1;
  1884. }
  1885. return(0);
  1886. }
  1887. #endif /* OS2 */
  1888. debug(F111,"TCP keepalive error: SO_KEEPALIVE","len",x);
  1889. debug(F111,
  1890. "TCP keepalive SO_KEEPALIVE",
  1891. "expected len",
  1892. sizeof(get_keepalive_opt)
  1893. );
  1894. debug(F111,
  1895. "TCP keepalive SO_KEEPALIVE",
  1896. "keepalive_opt",
  1897. get_keepalive_opt
  1898. );
  1899. } else if (get_keepalive_opt != onoff) {
  1900. set_keepalive_opt = onoff;
  1901. if (setsockopt(sock,
  1902. SOL_SOCKET,
  1903. SO_KEEPALIVE,
  1904. (char *)&set_keepalive_opt,
  1905. sizeof(set_keepalive_opt))
  1906. ) {
  1907. debug(F111,
  1908. "TCP keepalive can't clear SO_KEEPALIVE",
  1909. ck_errstr(),
  1910. errno
  1911. );
  1912. tcp_keepalive = get_keepalive_opt;
  1913. } else {
  1914. debug(F101,
  1915. "TCP keepalive new SO_KEEPALIVE",
  1916. "",
  1917. set_keepalive_opt
  1918. );
  1919. tcp_keepalive = onoff;
  1920. return 1;
  1921. }
  1922. } else {
  1923. debug(F101,"TCP keepalive SO_KEEPALIVE unchanged",
  1924. "",
  1925. get_keepalive_opt
  1926. );
  1927. tcp_keepalive = onoff;
  1928. return 1;
  1929. }
  1930. #else
  1931. debug(F100,"TCP keepalive SO_KEEPALIVE not defined","",0);
  1932. #endif /* SO_KEEPALIVE */
  1933. #else
  1934. debug(F100,"TCP keepalive SO_SOCKET not defined","",0);
  1935. #endif /* SOL_SOCKET */
  1936. return(0);
  1937. }
  1938. int
  1939. dontroute(sock,onoff) int sock; int onoff; {
  1940. #ifdef SOL_SOCKET
  1941. #ifdef SO_DONTROUTE
  1942. int get_dontroute_opt;
  1943. int set_dontroute_opt;
  1944. SOCKOPT_T x;
  1945. #ifdef IKSD
  1946. if (!inserver)
  1947. #endif /* IKSD */
  1948. if (sock == -1 ||
  1949. nettype != NET_TCPA && nettype != NET_TCPB && nettype != NET_SSH
  1950. || ttmdm >= 0) {
  1951. tcp_dontroute = onoff;
  1952. return 1;
  1953. }
  1954. x = sizeof(get_dontroute_opt);
  1955. if (getsockopt(sock,
  1956. SOL_SOCKET, SO_DONTROUTE, (char *)&get_dontroute_opt, &x)) {
  1957. debug(F111,"TCP dontroute can't get SO_DONTROUTE",ck_errstr(),errno);
  1958. } else if (x != sizeof(get_dontroute_opt)) {
  1959. #ifdef OS2
  1960. short get_dontroute_opt16;
  1961. short set_dontroute_opt16;
  1962. if (x == sizeof(get_dontroute_opt16)) {
  1963. debug(F111,"TCP dontroute warning: SO_DONTROUTE",
  1964. "len is 16-bit",x);
  1965. if (getsockopt(sock,
  1966. SOL_SOCKET, SO_DONTROUTE,
  1967. (char *)&get_dontroute_opt16, &x)
  1968. ) {
  1969. debug(F111,
  1970. "TCP dontroute can't get SO_DONTROUTE",
  1971. ck_errstr(),
  1972. errno
  1973. );
  1974. } else if (get_dontroute_opt16 != onoff) {
  1975. set_dontroute_opt16 = onoff;
  1976. if (setsockopt(sock,
  1977. SOL_SOCKET,
  1978. SO_DONTROUTE,
  1979. (char *)&set_dontroute_opt16,
  1980. sizeof(set_dontroute_opt16))
  1981. ) {
  1982. debug(F111,
  1983. "TCP dontroute can't clear SO_DONTROUTE",
  1984. ck_errstr(),
  1985. errno
  1986. );
  1987. tcp_dontroute = get_dontroute_opt16;
  1988. } else {
  1989. debug(F101,
  1990. "TCP dontroute new SO_DONTROUTE","",
  1991. set_dontroute_opt16);
  1992. tcp_dontroute = set_dontroute_opt16;
  1993. return 1;
  1994. }
  1995. } else {
  1996. debug(F101,"TCP dontroute SO_DONTROUTE unchanged","",
  1997. get_dontroute_opt16);
  1998. tcp_dontroute = onoff;
  1999. return 1;
  2000. }
  2001. return(0);
  2002. }
  2003. #endif /* OS2 */
  2004. debug(F111,"TCP dontroute error: SO_DONTROUTE","len",x);
  2005. debug(F111,
  2006. "TCP dontroute SO_DONTROUTE",
  2007. "expected len",
  2008. sizeof(get_dontroute_opt)
  2009. );
  2010. debug(F111,
  2011. "TCP dontroute SO_DONTROUTE",
  2012. "dontroute_opt",
  2013. get_dontroute_opt
  2014. );
  2015. } else if (get_dontroute_opt != onoff) {
  2016. set_dontroute_opt = onoff;
  2017. if (setsockopt(sock,
  2018. SOL_SOCKET,
  2019. SO_DONTROUTE,
  2020. (char *)&set_dontroute_opt,
  2021. sizeof(set_dontroute_opt))
  2022. ) {
  2023. debug(F111,
  2024. "TCP dontroute can't clear SO_DONTROUTE",
  2025. ck_errstr(),
  2026. errno
  2027. );
  2028. tcp_dontroute = get_dontroute_opt;
  2029. } else {
  2030. debug(F101,
  2031. "TCP dontroute new SO_DONTROUTE",
  2032. "",
  2033. set_dontroute_opt
  2034. );
  2035. tcp_dontroute = onoff;
  2036. return 1;
  2037. }
  2038. } else {
  2039. debug(F101,"TCP dontroute SO_DONTROUTE unchanged",
  2040. "",
  2041. get_dontroute_opt
  2042. );
  2043. tcp_dontroute = onoff;
  2044. return 1;
  2045. }
  2046. #else
  2047. debug(F100,"TCP dontroute SO_DONTROUTE not defined","",0);
  2048. #endif /* SO_DONTROUTE */
  2049. #else
  2050. debug(F100,"TCP dontroute SO_SOCKET not defined","",0);
  2051. #endif /* SOL_SOCKET */
  2052. return(0);
  2053. }
  2054. int
  2055. no_delay(sock,onoff) int sock; int onoff; {
  2056. #ifdef SOL_SOCKET
  2057. #ifdef TCP_NODELAY
  2058. int get_nodelay_opt;
  2059. int set_nodelay_opt;
  2060. SOCKOPT_T x;
  2061. #ifdef IKSD
  2062. if (!inserver)
  2063. #endif /* IKSD */
  2064. if (sock == -1 ||
  2065. nettype != NET_TCPA && nettype != NET_TCPB && nettype != NET_SSH
  2066. || ttmdm >= 0) {
  2067. tcp_nodelay = onoff;
  2068. return(1);
  2069. }
  2070. x = sizeof(get_nodelay_opt);
  2071. if (getsockopt(sock,IPPROTO_TCP,TCP_NODELAY,
  2072. (char *)&get_nodelay_opt,&x)) {
  2073. debug(F111,
  2074. "TCP no_delay can't get TCP_NODELAY",
  2075. ck_errstr(),
  2076. errno);
  2077. } else if (x != sizeof(get_nodelay_opt)) {
  2078. #ifdef OS2
  2079. short get_nodelay_opt16;
  2080. short set_nodelay_opt16;
  2081. if (x == sizeof(get_nodelay_opt16)) {
  2082. debug(F111,"TCP no_delay warning: TCP_NODELAY","len is 16-bit",x);
  2083. if (getsockopt(sock,
  2084. IPPROTO_TCP, TCP_NODELAY,
  2085. (char *)&get_nodelay_opt16, &x)
  2086. ) {
  2087. debug(F111,
  2088. "TCP no_delay can't get TCP_NODELAY",
  2089. ck_errstr(),
  2090. errno);
  2091. } else if (get_nodelay_opt16 != onoff) {
  2092. set_nodelay_opt16 = onoff;
  2093. if (setsockopt(sock,
  2094. IPPROTO_TCP,
  2095. TCP_NODELAY,
  2096. (char *)&set_nodelay_opt16,
  2097. sizeof(set_nodelay_opt16))
  2098. ) {
  2099. debug(F111,
  2100. "TCP no_delay can't clear TCP_NODELAY",
  2101. ck_errstr(),
  2102. errno);
  2103. tcp_nodelay = get_nodelay_opt16;
  2104. } else {
  2105. debug(F101,
  2106. "TCP no_delay new TCP_NODELAY",
  2107. "",
  2108. set_nodelay_opt16);
  2109. tcp_nodelay = onoff;
  2110. return 1;
  2111. }
  2112. } else {
  2113. debug(F101,"TCP no_delay TCP_NODELAY unchanged","",
  2114. get_nodelay_opt16);
  2115. tcp_nodelay = onoff;
  2116. return 1;
  2117. }
  2118. return(0);
  2119. }
  2120. #endif /* OS2 */
  2121. debug(F111,"TCP no_delay error: TCP_NODELAY","len",x);
  2122. debug(F111,"TCP no_delay TCP_NODELAY","expected len",
  2123. sizeof(get_nodelay_opt));
  2124. debug(F111,"TCP no_delay TCP_NODELAY","nodelay_opt",get_nodelay_opt);
  2125. } else if (get_nodelay_opt != onoff) {
  2126. set_nodelay_opt = onoff;
  2127. if (setsockopt(sock,
  2128. IPPROTO_TCP,
  2129. TCP_NODELAY,
  2130. (char *)&set_nodelay_opt,
  2131. sizeof(set_nodelay_opt))) {
  2132. debug(F111,
  2133. "TCP no_delay can't clear TCP_NODELAY",
  2134. ck_errstr(),
  2135. errno
  2136. );
  2137. tcp_nodelay = get_nodelay_opt;
  2138. } else {
  2139. debug(F101,"TCP no_delay new TCP_NODELAY","",set_nodelay_opt);
  2140. tcp_nodelay = onoff;
  2141. return 1;
  2142. }
  2143. } else {
  2144. debug(F101,"TCP no_delay TCP_NODELAY unchanged","",get_nodelay_opt);
  2145. tcp_nodelay = onoff;
  2146. return(1);
  2147. }
  2148. #else
  2149. debug(F100,"TCP no_delay TCP_NODELAY not defined","",0);
  2150. #endif /* TCP_NODELAY */
  2151. #else
  2152. debug(F100,"TCP no_delay SO_SOCKET not defined","",0);
  2153. #endif /* SOL_SOCKET */
  2154. return 0;
  2155. }
  2156. #endif /* datageneral */
  2157. #endif /* NOTCPOPTS */
  2158. #ifdef SUNX25
  2159. #ifndef X25_WR_FACILITY
  2160. /* For Solaris 2.3 / SunLink 8.x - see comments in ckcnet.h */
  2161. void
  2162. bzero(s,n) char *s; int n; {
  2163. memset(s,0,n);
  2164. }
  2165. #endif /* X25_WR_FACILITY */
  2166. #endif /* SUNX25 */
  2167. #ifdef TCPSOCKET
  2168. #ifndef OS2
  2169. #ifndef NOLISTEN
  2170. #ifdef BSDSELECT
  2171. #ifndef VMS
  2172. #ifndef BELLV10
  2173. #ifndef datageneral
  2174. #ifdef hp9000s500 /* HP-9000/500 HP-U 5.21 */
  2175. #include <time.h>
  2176. #else
  2177. /****** THIS SECTION ADDED BY STEVE RANCE - OS9 NETWORK SERVER
  2178. * ------------------------------------------------------
  2179. *
  2180. * Due to OS9's Lack of a select() call, the following seems to be
  2181. * enough to fool the rest of the code into compiling. The only
  2182. * effect that I can see is using control L to refresh the status
  2183. * display gets qued up until some network packets arrive.
  2184. *
  2185. * This solution is by no means elegant but works enough to be
  2186. * a (the) solution.
  2187. *
  2188. * Also with the defines I had specified in my makefile I had to
  2189. * have an #endif right at the end of the file when compiling.
  2190. * I did not bother speding time to find out why.
  2191. *
  2192. * COPTS = -to=osk -d=OSK -d=TCPSOCKET -d=SELECT -d=VOID=void -d=SIG_V \
  2193. * -d=DYNAMIC -d=PARSENSE -d=KANJI -d=MYCURSES -d=ZFCDAT \
  2194. * -d=CK_APC -d=CK_REDIR -d=RENAME -d=CK_TTYFD -d=NOOLDMODEMS \
  2195. * -d=CK_ANSIC -d=CK_XYZ -tp=68040d -l=netdb.l -l=socklib.l \
  2196. * -l=termlib.l -l=math.l -l=sys_clib.l
  2197. *
  2198. * stever@ozemail.com.au
  2199. */
  2200. #ifdef OSK
  2201. #define BSDSELECT /* switch on BSD select code */
  2202. #define FD_SETSIZE 32 /* Max # of paths in OS9 */
  2203. #define FD_ZERO(p) ((*p)=0)
  2204. #define FD_SET(n,b) ((*b)|=(1<<(n)))
  2205. #define FD_ISSET(n,b) 1 /* always say data is ready */
  2206. #define select(a,b,c,d,e) 1 /* always say 1 path has data */
  2207. typedef int fd_set; /* keep BSD Code Happy */
  2208. struct timeval {int tv_sec,tv_usec;}; /* keep BSD Code Happy */
  2209. /****** END OF OS9 MODS FROM STEVE RANCE **************************/
  2210. #endif /* OSK */
  2211. #include <sys/time.h>
  2212. #endif /* hp9000s500 */
  2213. #endif /* datageneral */
  2214. #endif /* BELLV10 */
  2215. #endif /* VMS */
  2216. #ifdef SELECT_H
  2217. #include <sys/select.h>
  2218. #endif /* SELECT_H */
  2219. #endif /* BSDSELECT */
  2220. #ifdef SELECT
  2221. #ifdef CK_SCOV5
  2222. #include <sys/select.h>
  2223. #endif /* CK_SCOV5 */
  2224. #endif /* SELECT */
  2225. #ifdef NOTUSED
  2226. /* T C P S O C K E T _ O P E N -- Open a preexisting socket number */
  2227. int
  2228. tcpsocket_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo {
  2229. int on = 1;
  2230. static struct servent *service, servrec;
  2231. static struct hostent *host;
  2232. static struct sockaddr_in saddr;
  2233. static
  2234. #ifdef UCX50
  2235. unsigned
  2236. #endif /* UCX50 */
  2237. int saddrlen;
  2238. #ifdef BSDSELECT
  2239. fd_set rfds;
  2240. struct timeval tv;
  2241. #else
  2242. #ifdef BELLSELECT
  2243. fd_set rfds;
  2244. #else
  2245. fd_set rfds;
  2246. fd_set rfds;
  2247. struct timeval {
  2248. long tv_sec;
  2249. long tv_usec;
  2250. } tv;
  2251. #endif /* BELLSELECT */
  2252. #endif /* BSDSELECT */
  2253. debug(F101,"tcpsocket_open nett","",nett);
  2254. *ipaddr = '\0';
  2255. if (nett != NET_TCPB)
  2256. return(-1); /* BSD socket support */
  2257. netclos(); /* Close any previous connection. */
  2258. ckstrncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
  2259. #ifdef COMMENT
  2260. /* Jeff's version from 30 Dec 2005 doesn't inhibit Telnet */
  2261. if (ttnproto != NP_TCPRAW &&
  2262. ttnproto != NP_SSL_RAW &&
  2263. ttnproto != NP_TLS_RAW)
  2264. ttnproto = NP_NONE; /* No protocol selected yet. */
  2265. #else
  2266. /* fdc's version from 4 Dec 2005 works ok */
  2267. if (ttnproto != NP_TCPRAW)
  2268. ttnproto = NP_NONE; /* No protocol selected yet. */
  2269. #endif /* COMMENT */
  2270. debug(F110,"tcpsocket_open namecopy",namecopy,0);
  2271. /* Assign the socket number to ttyfd and then fill in tcp structures */
  2272. ttyfd = atoi(&name[1]);
  2273. debug(F111,"tcpsocket_open","ttyfd",ttyfd);
  2274. #ifndef NOTCPOPTS
  2275. #ifdef SOL_SOCKET
  2276. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  2277. #ifndef datageneral
  2278. #ifdef TCP_NODELAY
  2279. no_delay(ttyfd,tcp_nodelay);
  2280. #endif /* TCP_NODELAY */
  2281. #ifdef SO_KEEPALIVE
  2282. keepalive(ttyfd,tcp_keepalive);
  2283. #endif /* SO_KEEPALIVE */
  2284. #ifdef SO_LINGER
  2285. ck_linger(ttyfd,tcp_linger, tcp_linger_tmo);
  2286. #endif /* SO_LINGER */
  2287. #ifdef SO_SNDBUF
  2288. sendbuf(ttyfd,tcp_sendbuf);
  2289. #endif /* SO_SNDBUF */
  2290. #ifdef SO_RCVBUF
  2291. recvbuf(ttyfd,tcp_recvbuf);
  2292. #endif /* SO_RCVBUF */
  2293. #endif /* datageneral */
  2294. #endif /* SOL_SOCKET */
  2295. #endif /* NOTCPOPTS */
  2296. #ifdef NT_TCP_OVERLAPPED
  2297. OverlappedWriteInit();
  2298. OverlappedReadInit();
  2299. #endif /* NT_TCP_OVERLAPPED */
  2300. /* Get the name of the host we are connected to */
  2301. saddrlen = sizeof(saddr);
  2302. getpeername(ttyfd,(struct sockaddr *)&saddr,&saddrlen);
  2303. ckstrncpy(ipaddr,(char *)inet_ntoa(saddr.sin_addr),20);
  2304. if (tcp_rdns == SET_ON
  2305. #ifdef CK_KERBEROS
  2306. || tcp_rdns == SET_AUTO &&
  2307. (ck_krb5_is_installed() || ck_krb4_is_installed())
  2308. #endif /* CK_KERBEROS */
  2309. #ifndef NOHTTP
  2310. && (tcp_http_proxy == NULL)
  2311. #endif /* NOHTTP */
  2312. #ifdef CK_SSL
  2313. && !(ssl_only_flag || tls_only_flag)
  2314. #endif /* CK_SSL */
  2315. ) { /* Reverse DNS */
  2316. if (!quiet) {
  2317. printf(" Reverse DNS Lookup... ");
  2318. fflush(stdout);
  2319. }
  2320. host = gethostbyaddr((char *)&saddr.sin_addr,4,PF_INET);
  2321. debug(F110,"tcpsocket_open gethostbyaddr",host ? "OK" : "FAILED",0);
  2322. if (host) {
  2323. host = ck_copyhostent(host);
  2324. debug(F100,"tcpsocket_open gethostbyaddr != NULL","",0);
  2325. if (!quiet) {
  2326. printf("(OK)\n");
  2327. fflush(stdout);
  2328. }
  2329. ckstrncpy(name, host->h_name, 80);
  2330. ckstrncat(name, ":", 80);
  2331. ckstrncat(name,ckuitoa(ntohs(saddr.sin_port)), 80);
  2332. if (!quiet
  2333. #ifndef NOICP
  2334. && !doconx
  2335. #endif /* NOICP */
  2336. )
  2337. printf("%s connected on port %d\n",
  2338. host->h_name,
  2339. ntohs(saddr.sin_port)
  2340. );
  2341. } else if (!quiet)
  2342. printf("Failed\n");
  2343. } else if (!quiet)
  2344. printf("(OK)\n");
  2345. if (tcp_rdns != SET_ON || !host) {
  2346. ckstrncpy(name,ipaddr,80);
  2347. ckstrncat(name,":",80);
  2348. ckstrncat(name,ckuitoa(ntohs(saddr.sin_port)),80);
  2349. if (!quiet
  2350. #ifdef NOICP
  2351. && !doconx
  2352. #endif /* NOICP */
  2353. )
  2354. printf("%s connected on port %d\n",ipaddr,ntohs(saddr.sin_port));
  2355. }
  2356. if (!quiet) fflush(stdout);
  2357. ttnet = nett; /* TCP/IP (sockets) network */
  2358. #ifdef RLOGCODE
  2359. if (ntohs(saddr.sin_port) == 513)
  2360. ttnproto = NP_LOGIN;
  2361. else
  2362. #endif /* RLOGCODE */
  2363. /* Assume the service is TELNET. */
  2364. #ifdef COMMENT
  2365. /* Jeff's code from 2005/12/30 */
  2366. if (ttnproto != NP_TCP_RAW &&
  2367. ttnproto != NP_SSL_RAW &&
  2368. ttnproto != NP_TLS_RAW)
  2369. #else
  2370. /* fdc's code from 2005/12/04 */
  2371. if (ttnproto != NP_TCPRAW)
  2372. #endif /* COMMENT */
  2373. ttnproto = NP_TELNET; /* Yes, set global flag. */
  2374. #ifdef CK_SECURITY
  2375. /* Before Initialization Telnet/Rlogin Negotiations Init Kerberos */
  2376. ck_auth_init((tcp_rdns && host && host->h_name && host->h_name[0]) ?
  2377. host->h_name : ipaddr,
  2378. ipaddr,
  2379. uidbuf,
  2380. ttyfd
  2381. );
  2382. #endif /* CK_SECURITY */
  2383. if (tn_ini() < 0) /* Start/Reset TELNET negotiations */
  2384. if (ttchk() < 0) /* Did it fail due to connect loss? */
  2385. return(-1);
  2386. if (*lcl < 0) *lcl = 1; /* Local mode. */
  2387. return(0); /* Done. */
  2388. }
  2389. #endif /* NOTUSED */
  2390. /* T C P S R V _ O P E N -- Open a TCP/IP Server connection */
  2391. /*
  2392. Calling conventions same as ttopen(), except third argument is network
  2393. type rather than modem type.
  2394. */
  2395. int
  2396. tcpsrv_open(name,lcl,nett,timo) char * name; int * lcl; int nett; int timo; {
  2397. char *p;
  2398. int i, x;
  2399. SOCKOPT_T on = 1;
  2400. int ready_to_accept = 0;
  2401. static struct servent *service, *service2, servrec;
  2402. static struct hostent *host;
  2403. static struct sockaddr_in saddr;
  2404. struct sockaddr_in l_addr;
  2405. GSOCKNAME_T l_slen;
  2406. #ifdef UCX50
  2407. static u_int saddrlen;
  2408. #else
  2409. static SOCKOPT_T saddrlen;
  2410. #endif /* UCX50 */
  2411. #ifdef BSDSELECT
  2412. fd_set rfds;
  2413. struct timeval tv;
  2414. #else
  2415. #ifdef BELLSELCT
  2416. fd_set rfds;
  2417. #else
  2418. fd_set rfds;
  2419. struct timeval {
  2420. long tv_sec;
  2421. long tv_usec;
  2422. } tv;
  2423. #endif /* BELLSELECT */
  2424. #endif /* BSDSELECT */
  2425. #ifdef CK_SSL
  2426. int ssl_failed = 0;
  2427. #endif /* CK_SSL */
  2428. debug(F101,"tcpsrv_open nett","",nett);
  2429. *ipaddr = '\0';
  2430. if (nett != NET_TCPB)
  2431. return(-1); /* BSD socket support */
  2432. netclos(); /* Close any previous connection. */
  2433. ckstrncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
  2434. /* Don't do this. */
  2435. #ifdef COMMENT
  2436. /* fdc */
  2437. if (ttnproto != NP_TCPRAW)
  2438. ttnproto = NP_NONE; /* No protocol selected yet. */
  2439. #endif /* COMMENT */
  2440. #ifdef COMMENT
  2441. /* Jeff */
  2442. if (ttnproto != NP_TCP_RAW &&
  2443. ttnproto != NP_SSL_RAW &&
  2444. ttnproto != NP_TLS_RAW)
  2445. ttnproto = NP_NONE; /* No protocol selected yet. */
  2446. #endif /* COMMENT */
  2447. debug(F110,"tcpsrv_open namecopy",namecopy,0);
  2448. p = namecopy; /* Was a service requested? */
  2449. while (*p != '\0' && *p != ':')
  2450. p++; /* Look for colon */
  2451. if (*p == ':') { /* Have a colon */
  2452. *p++ = '\0'; /* Get service name or number */
  2453. } else { /* Otherwise use kermit */
  2454. p = "kermit";
  2455. }
  2456. debug(F110,"tcpsrv_open service requested",p,0);
  2457. if (isdigit(*p)) { /* Use socket number without lookup */
  2458. service = &servrec;
  2459. service->s_port = htons((unsigned short)atoi(p));
  2460. } else { /* Otherwise lookup the service name */
  2461. service = getservbyname(p, "tcp");
  2462. }
  2463. if (!service && !strcmp("kermit",p)) { /* Use Kermit service port */
  2464. service = &servrec;
  2465. service->s_port = htons(1649);
  2466. }
  2467. #ifdef RLOGCODE
  2468. if (service && !strcmp("login",p) && service->s_port != htons(513)) {
  2469. fprintf(stderr,
  2470. " Warning: login service on port %d instead of port 513\n",
  2471. ntohs(service->s_port));
  2472. fprintf(stderr, " Edit SERVICES file if RLOGIN fails to connect.\n");
  2473. debug(F101,"tcpsrv_open login on port","",ntohs(service->s_port));
  2474. }
  2475. #endif /* RLOGCODE */
  2476. if (!service) {
  2477. fprintf(stderr, "Cannot find port for service: %s\n", p);
  2478. debug(F111,"tcpsrv_open can't get service",p,errno);
  2479. errno = 0; /* rather than mislead */
  2480. return(-1);
  2481. }
  2482. /* If we currently have a listen active but port has changed then close */
  2483. debug(F101,"tcpsrv_open checking previous connection","",tcpsrfd);
  2484. debug(F101,"tcpsrv_open previous tcpsrv_port","",tcpsrv_port);
  2485. if (tcpsrfd != -1 &&
  2486. tcpsrv_port != ntohs((unsigned short)service->s_port)) {
  2487. debug(F100,"tcpsrv_open closing previous connection","",0);
  2488. #ifdef TCPIPLIB
  2489. socket_close(tcpsrfd);
  2490. #else
  2491. close(tcpsrfd);
  2492. #endif /* TCPIPLIB */
  2493. tcpsrfd = -1;
  2494. }
  2495. debug(F100,"tcpsrv_open tcpsrfd","",tcpsrfd);
  2496. if (tcpsrfd == -1) {
  2497. /* Set up socket structure and get host address */
  2498. bzero((char *)&saddr, sizeof(saddr));
  2499. debug(F100,"tcpsrv_open bzero ok","",0);
  2500. saddr.sin_family = AF_INET;
  2501. if (tcp_address) {
  2502. #ifdef INADDRX
  2503. inaddrx = inet_addr(tcp_address);
  2504. saddr.sin_addr.s_addr = *(unsigned long *)&inaddrx;
  2505. #else
  2506. saddr.sin_addr.s_addr = inet_addr(tcp_address);
  2507. #endif /* INADDRX */
  2508. } else
  2509. saddr.sin_addr.s_addr = INADDR_ANY;
  2510. /* Get a file descriptor for the connection. */
  2511. saddr.sin_port = service->s_port;
  2512. ipaddr[0] = '\0';
  2513. debug(F100,"tcpsrv_open calling socket","",0);
  2514. if ((tcpsrfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  2515. perror("TCP socket error");
  2516. debug(F101,"tcpsrv_open socket error","",errno);
  2517. return (-1);
  2518. }
  2519. errno = 0;
  2520. /* Specify the Port may be reused */
  2521. debug(F100,"tcpsrv_open calling setsockopt","",0);
  2522. x = setsockopt(tcpsrfd,
  2523. SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof on);
  2524. debug(F101,"tcpsrv_open setsockopt","",x);
  2525. /* Now bind to the socket */
  2526. printf("\nBinding socket to port %d ...\n",
  2527. ntohs((unsigned short)service->s_port));
  2528. if (bind(tcpsrfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
  2529. i = errno; /* Save error code */
  2530. #ifdef TCPIPLIB
  2531. socket_close(tcpsrfd);
  2532. #else /* TCPIPLIB */
  2533. close(tcpsrfd);
  2534. #endif /* TCPIPLIB */
  2535. tcpsrfd = -1;
  2536. tcpsrv_port = 0;
  2537. ttyfd = -1;
  2538. wasclosed = 1;
  2539. errno = i; /* and report this error */
  2540. debug(F101,"tcpsrv_open bind errno","",errno);
  2541. printf("?Unable to bind to socket (errno = %d)\n",errno);
  2542. return(-1);
  2543. }
  2544. debug(F100,"tcpsrv_open bind OK","",0);
  2545. printf("Listening ...\n");
  2546. if (listen(tcpsrfd, 15) < 0) {
  2547. i = errno; /* Save error code */
  2548. #ifdef TCPIPLIB
  2549. socket_close(tcpsrfd);
  2550. #else /* TCPIPLIB */
  2551. close(tcpsrfd);
  2552. #endif /* TCPIPLIB */
  2553. tcpsrfd = -1;
  2554. tcpsrv_port = 0;
  2555. ttyfd = -1;
  2556. wasclosed = 1;
  2557. errno = i; /* And report this error */
  2558. debug(F101,"tcpsrv_open listen errno","",errno);
  2559. return(-1);
  2560. }
  2561. debug(F100,"tcpsrv_open listen OK","",0);
  2562. tcpsrv_port = ntohs((unsigned short)service->s_port);
  2563. }
  2564. #ifdef CK_SSL
  2565. if (ck_ssleay_is_installed()) {
  2566. if (!ssl_tn_init(SSL_SERVER)) {
  2567. ssl_failed = 1;
  2568. if (bio_err!=NULL) {
  2569. BIO_printf(bio_err,"do_ssleay_init() failed\n");
  2570. ERR_print_errors(bio_err);
  2571. } else {
  2572. fflush(stderr);
  2573. fprintf(stderr,"do_ssleay_init() failed\n");
  2574. ERR_print_errors_fp(stderr);
  2575. }
  2576. if (tls_only_flag || ssl_only_flag) {
  2577. #ifdef TCPIPLIB
  2578. socket_close(ttyfd);
  2579. socket_close(tcpsrfd);
  2580. #else /* TCPIPLIB */
  2581. close(ttyfd);
  2582. close(tcpsrfd);
  2583. #endif /* TCPIPLIB */
  2584. ttyfd = -1;
  2585. wasclosed = 1;
  2586. tcpsrfd = -1;
  2587. tcpsrv_port = 0;
  2588. return(-1);
  2589. }
  2590. /* we will continue to accept the connection */
  2591. /* without SSL or TLS support unless required. */
  2592. if ( TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) != TN_NG_MU )
  2593. TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
  2594. if ( TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) != TN_NG_MU )
  2595. TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  2596. if ( TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) != TN_NG_MU )
  2597. TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
  2598. if ( TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) != TN_NG_MU )
  2599. TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  2600. }
  2601. }
  2602. #endif /* CK_SSL */
  2603. printf("\nWaiting to Accept a TCP/IP connection on port %d ...\n",
  2604. ntohs((unsigned short)service->s_port));
  2605. saddrlen = sizeof(saddr);
  2606. #ifdef BSDSELECT
  2607. tv.tv_sec = tv.tv_usec = 0L;
  2608. if (timo < 0)
  2609. tv.tv_usec = (long) -timo * 10000L;
  2610. else
  2611. tv.tv_sec = timo;
  2612. debug(F101,"tcpsrv_open BSDSELECT","",timo);
  2613. #else
  2614. debug(F101,"tcpsrv_open not BSDSELECT","",timo);
  2615. #endif /* BSDSELECT */
  2616. if (timo) {
  2617. while (!ready_to_accept) {
  2618. #ifdef BSDSELECT
  2619. FD_ZERO(&rfds);
  2620. FD_SET(tcpsrfd, &rfds);
  2621. ready_to_accept =
  2622. ((select(FD_SETSIZE,
  2623. #ifdef HPUX
  2624. #ifdef HPUX1010
  2625. (fd_set *)
  2626. #else
  2627. (int *)
  2628. #endif /* HPUX1010 */
  2629. #else
  2630. #ifdef __DECC
  2631. #ifdef INTSELECT
  2632. (int *)
  2633. #else /* def INTSELECT */
  2634. (fd_set *)
  2635. #endif /* def INTSELECT [else] */
  2636. #endif /* __DECC */
  2637. #endif /* HPUX */
  2638. &rfds, NULL, NULL, &tv) > 0) &&
  2639. FD_ISSET(tcpsrfd, &rfds));
  2640. #else /* BSDSELECT */
  2641. #ifdef IBMSELECT
  2642. #define ck_sleepint 250
  2643. ready_to_accept =
  2644. (select(&tcpsrfd, 1, 0, 0,
  2645. timo < 0 ? -timo :
  2646. (timo > 0 ? timo * 1000L : ck_sleepint)) == 1
  2647. );
  2648. #else
  2649. #ifdef BELLSELECT
  2650. FD_ZERO(rfds);
  2651. FD_SET(tcpsrfd, rfds);
  2652. ready_to_accept =
  2653. ((select(128, rfds, NULL, NULL, timo < 0 ? -timo :
  2654. (timo > 0 ? timo * 1000L)) > 0) &&
  2655. FD_ISSET(tcpsrfd, rfds));
  2656. #else
  2657. /* Try this - what's the worst that can happen... */
  2658. FD_ZERO(&rfds);
  2659. FD_SET(tcpsrfd, &rfds);
  2660. ready_to_accept =
  2661. ((select(FD_SETSIZE,
  2662. (fd_set *) &rfds, NULL, NULL, &tv) > 0) &&
  2663. FD_ISSET(tcpsrfd, &rfds));
  2664. #endif /* BELLSELECT */
  2665. #endif /* IBMSELECT */
  2666. #endif /* BSDSELECT */
  2667. }
  2668. }
  2669. if (ready_to_accept || timo == 0) {
  2670. if ((ttyfd = accept(tcpsrfd,
  2671. (struct sockaddr *)&saddr,&saddrlen)) < 0) {
  2672. i = errno; /* save error code */
  2673. #ifdef TCPIPLIB
  2674. socket_close(tcpsrfd);
  2675. #else /* TCPIPLIB */
  2676. close(tcpsrfd);
  2677. #endif /* TCPIPLIB */
  2678. ttyfd = -1;
  2679. wasclosed = 1;
  2680. tcpsrfd = -1;
  2681. tcpsrv_port = 0;
  2682. errno = i; /* and report this error */
  2683. debug(F101,"tcpsrv_open accept errno","",errno);
  2684. return(-1);
  2685. }
  2686. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  2687. #ifndef NOTCPOPTS
  2688. #ifndef datageneral
  2689. #ifdef SOL_SOCKET
  2690. #ifdef TCP_NODELAY
  2691. no_delay(ttyfd,tcp_nodelay);
  2692. debug(F101,"tcpsrv_open no_delay","",tcp_nodelay);
  2693. #endif /* TCP_NODELAY */
  2694. #ifdef SO_KEEPALIVE
  2695. keepalive(ttyfd,tcp_keepalive);
  2696. debug(F101,"tcpsrv_open keepalive","",tcp_keepalive);
  2697. #endif /* SO_KEEPALIVE */
  2698. #ifdef SO_LINGER
  2699. ck_linger(ttyfd,tcp_linger, tcp_linger_tmo);
  2700. debug(F101,"tcpsrv_open linger","",tcp_linger_tmo);
  2701. #endif /* SO_LINGER */
  2702. #ifdef SO_SNDBUF
  2703. sendbuf(ttyfd,tcp_sendbuf);
  2704. #endif /* SO_SNDBUF */
  2705. #ifdef SO_RCVBUF
  2706. recvbuf(ttyfd,tcp_recvbuf);
  2707. #endif /* SO_RCVBUF */
  2708. #endif /* SOL_SOCKET */
  2709. #endif /* datageneral */
  2710. #endif /* NOTCPOPTS */
  2711. ttnet = nett; /* TCP/IP (sockets) network */
  2712. tcp_incoming = 1; /* This is an incoming connection */
  2713. sstelnet = 1; /* Do server-side Telnet protocol */
  2714. /* See if the service is TELNET. */
  2715. x = (unsigned short)service->s_port;
  2716. service2 = getservbyname("telnet", "tcp");
  2717. if (service2 && x == service2->s_port) {
  2718. #ifdef COMMENT
  2719. /* Jeff 2005/12/30 */
  2720. if (ttnproto != NP_TCPRAW && /* Yes... */
  2721. ttnproto != NP_SSL_RAW &&
  2722. ttnproto != NP_TLS_RAW) /* and if raw port not requested */
  2723. #else
  2724. /* fdc 2005/12/04 */
  2725. if (ttnproto != NP_TCPRAW) /* Yes and if raw port not requested */
  2726. #endif /* */
  2727. ttnproto = NP_TELNET; /* set protocol to TELNET. */
  2728. }
  2729. ckstrncpy(ipaddr,(char *)inet_ntoa(saddr.sin_addr),20);
  2730. if (tcp_rdns) {
  2731. if (!quiet) {
  2732. printf(" Reverse DNS Lookup... ");
  2733. fflush(stdout);
  2734. }
  2735. if (host = gethostbyaddr((char *)&saddr.sin_addr,4,PF_INET)) {
  2736. host = ck_copyhostent(host);
  2737. debug(F100,"tcpsrv_open gethostbyaddr != NULL","",0);
  2738. if (!quiet) {
  2739. printf("(OK)\n");
  2740. fflush(stdout);
  2741. }
  2742. name[0] = '*';
  2743. ckstrncpy(&name[1],host->h_name,78);
  2744. ckstrncat(name,":",80-strlen(name));
  2745. ckstrncat(name,p,80-strlen(name));
  2746. if (!quiet
  2747. #ifndef NOICP
  2748. && !doconx
  2749. #endif /* NOICP */
  2750. )
  2751. printf("%s connected on port %s\n",host->h_name,p);
  2752. } else {
  2753. if (!quiet) printf("Failed.\n");
  2754. }
  2755. } else if (!quiet) printf("(OK)\n");
  2756. if (!tcp_rdns || !host) {
  2757. ckstrncpy(name,ipaddr,80);
  2758. ckstrncat(name,":",80);
  2759. ckstrncat(name,ckuitoa(ntohs(saddr.sin_port)),80);
  2760. if (!quiet
  2761. #ifndef NOICP
  2762. && !doconx
  2763. #endif /* NOICP */
  2764. )
  2765. printf("%s connected on port %d\n",ipaddr,ntohs(saddr.sin_port));
  2766. }
  2767. if (!quiet) fflush(stdout);
  2768. #ifdef CK_SECURITY
  2769. /* Before Initialization Telnet/Rlogin Negotiations Init Kerberos */
  2770. ck_auth_init((tcp_rdns && host && host->h_name && host->h_name[0]) ?
  2771. (char *)host->h_name : ipaddr,
  2772. ipaddr,
  2773. uidbuf,
  2774. ttyfd
  2775. );
  2776. #endif /* CK_SECURITY */
  2777. #ifdef CK_SSL
  2778. if (ck_ssleay_is_installed() && !ssl_failed) {
  2779. if (ck_ssl_incoming(ttyfd) < 0) {
  2780. #ifdef TCPIPLIB
  2781. socket_close(ttyfd);
  2782. socket_close(tcpsrfd);
  2783. #else /* TCPIPLIB */
  2784. close(ttyfd);
  2785. close(tcpsrfd);
  2786. #endif /* TCPIPLIB */
  2787. ttyfd = -1;
  2788. wasclosed = 1;
  2789. tcpsrfd = -1;
  2790. tcpsrv_port = 0;
  2791. return(-1);
  2792. }
  2793. }
  2794. #endif /* CK_SSL */
  2795. #ifndef datageneral
  2796. /* Find out our own IP address. */
  2797. l_slen = sizeof(l_addr);
  2798. bzero((char *)&l_addr, l_slen);
  2799. #ifndef EXCELAN
  2800. if (!getsockname(ttyfd, (struct sockaddr *)&l_addr, &l_slen)) {
  2801. char * s = (char *)inet_ntoa(l_addr.sin_addr);
  2802. ckstrncpy(myipaddr, s,20);
  2803. debug(F110,"getsockname",myipaddr,0);
  2804. }
  2805. #endif /* EXCELAN */
  2806. #endif /* datageneral */
  2807. if (tn_ini() < 0) /* Start TELNET negotiations. */
  2808. if (ttchk() < 0) { /* Disconnected? */
  2809. i = errno; /* save error code */
  2810. #ifdef TCPIPLIB
  2811. socket_close(tcpsrfd);
  2812. #else /* TCPIPLIB */
  2813. close(tcpsrfd);
  2814. #endif /* TCPIPLIB */
  2815. ttyfd = -1;
  2816. wasclosed = 1;
  2817. tcpsrfd = -1;
  2818. tcpsrv_port = 0;
  2819. errno = i; /* and report this error */
  2820. debug(F101,"tcpsrv_open accept errno","",errno);
  2821. return(-1);
  2822. }
  2823. debug(F101,"tcpsrv_open service","",x);
  2824. if (*lcl < 0) /* Set local mode. */
  2825. *lcl = 1;
  2826. #ifdef CK_KERBEROS
  2827. #ifdef KRB5_U2U
  2828. if ( ttnproto == NP_K5U2U ) {
  2829. if (k5_user_to_user_server_auth() != 0) {
  2830. i = errno; /* save error code */
  2831. #ifdef TCPIPLIB
  2832. socket_close(tcpsrfd);
  2833. #else /* TCPIPLIB */
  2834. close(tcpsrfd);
  2835. #endif /* TCPIPLIB */
  2836. ttyfd = -1;
  2837. wasclosed = 1;
  2838. tcpsrfd = -1;
  2839. tcpsrv_port = 0;
  2840. errno = i; /* and report this error */
  2841. debug(F101,"tcpsrv_open accept errno","",errno);
  2842. return(-1);
  2843. }
  2844. }
  2845. #endif /* KRB5_U2U */
  2846. #endif /* CK_KERBEROS */
  2847. return(0); /* Done. */
  2848. } else {
  2849. i = errno; /* save error code */
  2850. #ifdef TCPIPLIB
  2851. socket_close(tcpsrfd);
  2852. #else /* TCPIPLIB */
  2853. close(tcpsrfd);
  2854. #endif /* TCPIPLIB */
  2855. ttyfd = -1;
  2856. wasclosed = 1;
  2857. tcpsrfd = -1;
  2858. tcpsrv_port = 0;
  2859. errno = i; /* and report this error */
  2860. debug(F101,"tcpsrv_open accept errno","",errno);
  2861. return(-1);
  2862. }
  2863. }
  2864. #endif /* NOLISTEN */
  2865. #endif /* OS2 */
  2866. #endif /* TCPSOCKET */
  2867. #endif /* NONET */
  2868. #ifdef TCPSOCKET
  2869. char *
  2870. ckname2addr(name) char * name;
  2871. {
  2872. #ifdef HPUX5
  2873. return("");
  2874. #else
  2875. struct hostent *host;
  2876. if (name == NULL || *name == '\0')
  2877. return("");
  2878. host = gethostbyname(name);
  2879. if ( host ) {
  2880. host = ck_copyhostent(host);
  2881. return(inet_ntoa(*((struct in_addr *) host->h_addr)));
  2882. }
  2883. return("");
  2884. #endif /* HPUX5 */
  2885. }
  2886. char *
  2887. ckaddr2name(addr) char * addr;
  2888. {
  2889. #ifdef HPUX5
  2890. return("");
  2891. #else
  2892. struct hostent *host;
  2893. struct in_addr sin_addr;
  2894. if (addr == NULL || *addr == '\0')
  2895. return("");
  2896. sin_addr.s_addr = inet_addr(addr);
  2897. host = gethostbyaddr((char *)&sin_addr,4,AF_INET);
  2898. if (host) {
  2899. host = ck_copyhostent(host);
  2900. return((char *)host->h_name);
  2901. }
  2902. return("");
  2903. #endif /* HPUX5 */
  2904. }
  2905. #endif /* TCPSOCKET */
  2906. unsigned long peerxipaddr = 0L;
  2907. char *
  2908. ckgetpeer() {
  2909. #ifdef TCPSOCKET
  2910. static char namebuf[256];
  2911. static struct hostent *host;
  2912. static struct sockaddr_in saddr;
  2913. #ifdef GPEERNAME_T
  2914. static GPEERNAME_T saddrlen;
  2915. #else
  2916. #ifdef PTX
  2917. static size_t saddrlen;
  2918. #else
  2919. #ifdef AIX42
  2920. /* It's size_t in 4.2 but int in 4.1 and earlier. */
  2921. /* Note: the 4.2 man page lies; believe socket.h. */
  2922. static size_t saddrlen;
  2923. #else
  2924. #ifdef UNIXWARE
  2925. static size_t saddrlen;
  2926. #else /* UNIXWARE */
  2927. #ifdef DEC_TCPIP
  2928. /* 2010-03-08 SMS.
  2929. * Coincidentally, the condition for integer arguments in select(),
  2930. * which is actually "defined( _DECC_V4_SOURCE)", works for an integer
  2931. * argument in getpeername(). Sadly, due to a lack of foresight,
  2932. * "defined( _DECC_V4_SOURCE)" doesn't work with DEC C V4.0, so the
  2933. * user-specified INTSELECT is used instead. Most likely, "size_t"
  2934. * should be used instead of "unsigned int", but I'm a coward.
  2935. */
  2936. #ifdef INTSELECT
  2937. static int saddrlen;
  2938. #else /* def INTSELECT */
  2939. static unsigned int saddrlen;
  2940. #endif /* def INTSELECT [else] */
  2941. #else
  2942. #ifdef MACOSX10
  2943. static unsigned int saddrlen;
  2944. #else
  2945. #ifdef CK_64BIT
  2946. static socklen_t saddrlen;
  2947. #else
  2948. static int saddrlen;
  2949. #endif /* CK_64BIT */
  2950. #endif /* MACOSX10 */
  2951. #endif /* DEC_TCPIP */
  2952. #endif /* UNIXWARE */
  2953. #endif /* AIX42 */
  2954. #endif /* PTX */
  2955. #endif /* GPEERNAME_T */
  2956. saddrlen = sizeof(saddr);
  2957. if (getpeername(ttyfd,(struct sockaddr *)&saddr,&saddrlen) < 0) {
  2958. debug(F111,"ckgetpeer failure",ckitoa(ttyfd),errno);
  2959. return(NULL);
  2960. }
  2961. host = gethostbyaddr((char *)&saddr.sin_addr,4,AF_INET);
  2962. if (host) {
  2963. host = ck_copyhostent(host);
  2964. ckstrncpy(namebuf,(char *)host->h_name,80);
  2965. } else {
  2966. ckstrncpy(namebuf,(char *)inet_ntoa(saddr.sin_addr),80);
  2967. }
  2968. peerxipaddr = ntohl(saddr.sin_addr.s_addr);
  2969. debug(F111,"ckgetpeer",namebuf,peerxipaddr);
  2970. return(namebuf);
  2971. #else
  2972. return(NULL);
  2973. #endif /* TCPSOCKET */
  2974. }
  2975. /* Get fully qualified IP hostname */
  2976. #ifndef NONET
  2977. char *
  2978. #ifdef CK_ANSIC
  2979. ckgetfqhostname(char * name)
  2980. #else
  2981. ckgetfqhostname(name) char * name;
  2982. #endif /* CK_ANSIC */
  2983. {
  2984. #ifdef NOCKGETFQHOST
  2985. return(name);
  2986. #else /* If the following code dumps core, define NOCKGETFQHOST and rebuild. */
  2987. static char namebuf[256];
  2988. struct hostent *host=NULL;
  2989. struct sockaddr_in r_addr;
  2990. int i;
  2991. debug(F110,"ckgetfqhn()",name,0);
  2992. ckstrncpy(namebuf,name,256);
  2993. namebuf[255] = '\0';
  2994. i = ckindex(":",namebuf,0,0,0);
  2995. if (i)
  2996. namebuf[i-1] = '\0';
  2997. bzero((char *)&r_addr, sizeof(r_addr));
  2998. host = gethostbyname(namebuf);
  2999. if (host) {
  3000. host = ck_copyhostent(host);
  3001. debug(F100,"ckgetfqhn() gethostbyname != NULL","",0);
  3002. r_addr.sin_family = host->h_addrtype;
  3003. #ifdef HADDRLIST
  3004. #ifdef h_addr
  3005. /* This is for trying multiple IP addresses - see <netdb.h> */
  3006. if (!(host->h_addr_list))
  3007. goto exit_func;
  3008. bcopy(host->h_addr_list[0],
  3009. (caddr_t)&r_addr.sin_addr,
  3010. host->h_length
  3011. );
  3012. #else
  3013. bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
  3014. #endif /* h_addr */
  3015. #else /* HADDRLIST */
  3016. bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
  3017. #endif /* HADDRLIST */
  3018. #ifdef COMMENT
  3019. #ifndef EXCELAN
  3020. debug(F111,"BCOPY","host->h_addr",host->h_addr);
  3021. #endif /* EXCELAN */
  3022. debug(F111,"BCOPY"," (caddr_t)&r_addr.sin_addr",
  3023. (caddr_t)&r_addr.sin_addr);
  3024. #endif /* COMMENT */
  3025. debug(F111,"BCOPY","host->h_length",host->h_length);
  3026. #ifdef NT
  3027. /* Windows 95/98 requires a 1 second wait between calls to Microsoft */
  3028. /* provided DNS functions. Otherwise, the TTL of the DNS response */
  3029. /* is ignored. */
  3030. if (isWin95())
  3031. sleep(1);
  3032. #endif /* NT */
  3033. host = gethostbyaddr((char *)&r_addr.sin_addr,4,PF_INET);
  3034. if (host) {
  3035. host = ck_copyhostent(host);
  3036. debug(F100,"ckgetfqhn() gethostbyaddr != NULL","",0);
  3037. ckstrncpy(namebuf, host->h_name, 256);
  3038. }
  3039. }
  3040. #ifdef HADDRLIST
  3041. #ifdef h_addr
  3042. exit_func:
  3043. #endif /* h_addr */
  3044. #endif /* HADDRLIST */
  3045. if (i > 0)
  3046. ckstrncat(namebuf,&name[i-1],256-strlen(namebuf)-strlen(&name[i-1]));
  3047. debug(F110,"ckgetfqhn()",namebuf,0);
  3048. return(namebuf);
  3049. #endif /* NOCKGETFQHOST */
  3050. }
  3051. VOID
  3052. #ifdef CK_ANSIC
  3053. setnproto(char * p)
  3054. #else
  3055. setnproto(p) char * p;
  3056. #endif /* CK_ANSIC */
  3057. {
  3058. if (!isdigit(*p)) {
  3059. if (!strcmp("kermit",p))
  3060. ttnproto = NP_KERMIT;
  3061. else if (!strcmp("telnet",p))
  3062. ttnproto = NP_TELNET;
  3063. else if (!strcmp("http",p))
  3064. ttnproto = NP_TCPRAW;
  3065. #ifdef RLOGCODE
  3066. else if (!strcmp("login",p))
  3067. ttnproto = NP_RLOGIN;
  3068. #endif /* RLOGCODE */
  3069. #ifdef CK_SSL
  3070. /* Commonly used SSL ports (might not be in services file) */
  3071. else if (!strcmp("https",p)) {
  3072. ttnproto = NP_SSL_RAW;
  3073. ssl_only_flag = 1;
  3074. } else if (!strcmp("ssl-telnet",p)) {
  3075. ttnproto = NP_TELNET;
  3076. ssl_only_flag = 1;
  3077. } else if (!strcmp("telnets",p)) {
  3078. ttnproto = NP_TELNET;
  3079. ssl_only_flag = 1;
  3080. }
  3081. #endif /* CK_SSL */
  3082. #ifdef CK_KERBEROS
  3083. #ifdef RLOGCODE
  3084. else if (!strcmp("klogin",p)) {
  3085. if (ck_krb5_is_installed())
  3086. ttnproto = NP_K5LOGIN;
  3087. else if (ck_krb4_is_installed())
  3088. ttnproto = NP_K4LOGIN;
  3089. else
  3090. ttnproto = NP_RLOGIN;
  3091. } else if (!strcmp("eklogin",p)) {
  3092. if (ck_krb5_is_installed())
  3093. ttnproto = NP_EK5LOGIN;
  3094. else if (ck_krb4_is_installed())
  3095. ttnproto = NP_EK4LOGIN;
  3096. else
  3097. ttnproto = NP_RLOGIN;
  3098. }
  3099. #endif /* RLOGCODE */
  3100. #endif /* CK_KERBEROS */
  3101. else
  3102. ttnproto = NP_NONE;
  3103. } else {
  3104. switch (atoi(p)) {
  3105. case 23: /* Telnet */
  3106. ttnproto = NP_TELNET;
  3107. break;
  3108. case 513:
  3109. ttnproto = NP_RLOGIN;
  3110. break;
  3111. case 1649:
  3112. ttnproto = NP_KERMIT;
  3113. break;
  3114. #ifdef CK_SSL
  3115. case 443:
  3116. #ifdef COMMENT
  3117. /* Jeff 2005/12/30 */
  3118. ttnproto = NP_SSL_RAW;
  3119. #else
  3120. /* fdc 2005/12/04 */
  3121. ttnproto = NP_SSL;
  3122. #endif /* COMMENT */
  3123. ssl_only_flag = 1;
  3124. break;
  3125. case 151:
  3126. case 992:
  3127. ttnproto = NP_TELNET;
  3128. ssl_only_flag = 1;
  3129. break;
  3130. #endif /* CK_SSL */
  3131. #ifdef CK_KERBEROS
  3132. case 543:
  3133. if (ck_krb5_is_installed())
  3134. ttnproto = NP_K5LOGIN;
  3135. else if (ck_krb4_is_installed())
  3136. ttnproto = NP_K4LOGIN;
  3137. else
  3138. ttnproto = NP_RLOGIN;
  3139. break;
  3140. case 2105:
  3141. if (ck_krb5_is_installed())
  3142. ttnproto = NP_EK5LOGIN;
  3143. else if (ck_krb4_is_installed())
  3144. ttnproto = NP_EK4LOGIN;
  3145. else
  3146. ttnproto = NP_RLOGIN;
  3147. break;
  3148. #endif /* CK_KERBEROS */
  3149. case 80: /* HTTP */
  3150. ttnproto = NP_TCPRAW;
  3151. break;
  3152. default:
  3153. ttnproto = NP_NONE;
  3154. break;
  3155. }
  3156. }
  3157. }
  3158. /* ckgetservice() is used to determine the port number for a given */
  3159. /* service taking into account the use of DNS SRV records. */
  3160. static struct servent servrec;
  3161. static struct servent *
  3162. ckgetservice(hostname, servicename, ip, iplen)
  3163. char *hostname; char * servicename; char * ip; int iplen;
  3164. {
  3165. struct servent * service = NULL;
  3166. #ifdef CK_DNS_SRV
  3167. struct sockaddr * dns_addrs = NULL;
  3168. int dns_naddrs = 0;
  3169. #endif /* CK_DNS_SRV */
  3170. if (isdigit(*servicename)) { /* Use socket number without lookup */
  3171. service = &servrec;
  3172. service->s_port = htons((unsigned short)atoi(servicename));
  3173. } else { /* Otherwise lookup the service name */
  3174. #ifdef CK_DNS_SRV
  3175. if (tcp_dns_srv && !quiet) {
  3176. printf(" DNS SRV Lookup... ");
  3177. fflush(stdout);
  3178. }
  3179. if (tcp_dns_srv &&
  3180. locate_srv_dns(hostname,
  3181. servicename,
  3182. "tcp",
  3183. &dns_addrs,
  3184. &dns_naddrs
  3185. )
  3186. ) {
  3187. /* Use the first one. Eventually we should cycle through all */
  3188. /* the returned IP addresses and port numbers. */
  3189. struct sockaddr_in *sin = NULL;
  3190. #ifdef BETADEBUG
  3191. int i;
  3192. printf("\r\n");
  3193. for ( i=0;i<dns_naddrs;i++ ) {
  3194. sin = (struct sockaddr_in *) &dns_addrs[i];
  3195. printf("dns_addrs[%d] = %s %d\r\n", i,
  3196. (char *)inet_ntoa(sin->sin_addr),
  3197. ntohs(sin->sin_port));
  3198. }
  3199. #endif /* BETADEBUG */
  3200. sin = (struct sockaddr_in *) &dns_addrs[0];
  3201. if ( ip && iplen > 0 )
  3202. ckstrncpy(ip,(char *)inet_ntoa(sin->sin_addr),iplen);
  3203. service = &servrec;
  3204. service->s_port = sin->sin_port;
  3205. free(dns_addrs);
  3206. dns_addrs = NULL;
  3207. dns_naddrs = 0;
  3208. } else
  3209. #endif /* CK_DNS_SRV */
  3210. service = getservbyname(servicename, "tcp");
  3211. }
  3212. if (!service) {
  3213. if (!ckstrcmp("kermit",servicename,-1,0)) { /* Kermit service port */
  3214. service = &servrec;
  3215. service->s_port = htons(1649);
  3216. } else if (!ckstrcmp("telnet",servicename,-1,0)) { /* Telnet port */
  3217. service = &servrec;
  3218. service->s_port = htons(23);
  3219. } else if (!ckstrcmp("http",servicename,-1,0)) {
  3220. service = &servrec;
  3221. service->s_port = htons(80);
  3222. }
  3223. #ifdef RLOGCODE
  3224. else if (!ckstrcmp("login",servicename,-1,0)) {
  3225. service = &servrec;
  3226. service->s_port = htons(513);
  3227. }
  3228. #endif /* RLOGCODE */
  3229. #ifdef CK_SSL
  3230. /* Commonly used SSL ports (might not be in services file) */
  3231. else if (!ckstrcmp("https",servicename,-1,0)) {
  3232. service = &servrec;
  3233. service->s_port = htons(443);
  3234. } else if (!ckstrcmp("ssl-telnet",servicename,-1,0)) {
  3235. service = &servrec;
  3236. service->s_port = htons(151);
  3237. } else if (!ckstrcmp("telnets",servicename,-1,0)) {
  3238. service = &servrec;
  3239. service->s_port = htons(992);
  3240. }
  3241. #endif /* CK_SSL */
  3242. #ifdef CK_KERBEROS
  3243. #ifdef RLOGCODE
  3244. else if (!ckstrcmp("klogin",servicename,-1,0)) {
  3245. service = &servrec;
  3246. service->s_port = htons(543);
  3247. } else if (!ckstrcmp("eklogin",servicename,-1,0)) {
  3248. service = &servrec;
  3249. service->s_port = htons(2105);
  3250. }
  3251. #endif /* RLOGCODE */
  3252. #endif /* CK_KERBEROS */
  3253. }
  3254. return(service);
  3255. }
  3256. /* N E T O P E N -- Open a network connection */
  3257. /*
  3258. Calling conventions same as ttopen(), except third argument is network
  3259. type rather than modem type. Designed to be called from within ttopen.
  3260. */
  3261. #define XXNAMELEN 256
  3262. static char xxname[XXNAMELEN];
  3263. int
  3264. netopen(name, lcl, nett) char *name; int *lcl, nett; {
  3265. char *p;
  3266. int i, x, rc_inet_addr = 0, dns = 0;
  3267. #ifdef TCPSOCKET
  3268. int isconnect = 0;
  3269. #ifdef SO_OOBINLINE
  3270. int on = 1;
  3271. #endif /* SO_OOBINLINE */
  3272. struct servent *service=NULL;
  3273. struct hostent *host=NULL;
  3274. struct sockaddr_in r_addr;
  3275. struct sockaddr_in sin;
  3276. struct sockaddr_in l_addr;
  3277. GSOCKNAME_T l_slen;
  3278. #ifdef EXCELAN
  3279. struct sockaddr_in send_socket;
  3280. #endif /* EXCELAN */
  3281. #ifdef INADDRX
  3282. /* inet_addr() is of type struct in_addr */
  3283. #ifdef datageneral
  3284. extern struct in_addr inet_addr();
  3285. #else
  3286. #ifdef HPUX5WINTCP
  3287. extern struct in_addr inet_addr();
  3288. #endif /* HPUX5WINTCP */
  3289. #endif /* datageneral */
  3290. struct in_addr iax;
  3291. #else
  3292. #ifdef INADDR_NONE
  3293. struct in_addr iax;
  3294. #else /* INADDR_NONE */
  3295. long iax;
  3296. #endif /* INADDR_NONE */
  3297. #endif /* INADDRX */
  3298. #endif /* TCPSOCKET */
  3299. #ifdef COMMENT
  3300. /* This causes big trouble */
  3301. #ifndef INADDR_NONE
  3302. #define INADDR_NONE 0xffffffff
  3303. #endif /* INADDR_NONE */
  3304. #endif /* COMMENT */
  3305. #ifdef SUNX25 /* Code for SunLink X.25 support */
  3306. #define X29PID 1 /* X.29 Protocol ID */
  3307. _PROTOTYP(SIGTYP x25oobh, (int) );
  3308. CONN_DB x25host;
  3309. #ifndef X25_WR_FACILITY
  3310. FACILITY x25facil;
  3311. #else
  3312. FACILITY_DB x25facil;
  3313. #endif /* X25_WR_FACILITY */
  3314. static int needh = 1;
  3315. PID_T pid;
  3316. extern int linkid, lcn, x25ver;
  3317. #endif /* SUNX25 */
  3318. #ifdef ANYX25
  3319. extern int revcall, closgr, cudata;
  3320. extern char udata[];
  3321. #endif /* ANYX25 */
  3322. #ifdef IBMX25 /* Variables for IBM X25 */
  3323. extern int x25port; /* Logical port to use */
  3324. extern x25addr_t local_nua; /* Local X.25 address */
  3325. extern x25addr_t remote_nua; /* Remote X.25 address */
  3326. extern char x25name[]; /* X25 device name (sx25a0) */
  3327. extern char x25dev[]; /* X25 device file /dev/x25pkt */
  3328. ulong bind_flags = 0; /* Flags for binding the X25 stream */
  3329. ulong token = 0; /* Temporary return code */
  3330. #endif /* IBMX25 */
  3331. debug(F101,"netopen nett","",nett);
  3332. *ipaddr = '\0'; /* Initialize IP address string */
  3333. #ifdef SUNX25
  3334. if (nett == NET_SX25) { /* If network type is X.25 */
  3335. netclos(); /* Close any previous net connection */
  3336. ttnproto = NP_NONE; /* No protocol selected yet */
  3337. /* Set up host structure */
  3338. bzero((char *)&x25host,sizeof(x25host));
  3339. if ((x25host.hostlen = pkx121(name,x25host.host)) < 0) {
  3340. fprintf (stderr,"Invalid X.121 host address %s\n",name);
  3341. errno = 0;
  3342. return (-1);
  3343. }
  3344. x25host.datalen = X29PIDLEN;
  3345. x25host.data[0] = X29PID;
  3346. /* Set call user data if specified */
  3347. if (cudata) {
  3348. ckstrncpy((char *)x25host.data+X29PIDLEN,udata,(int)strlen(udata));
  3349. x25host.datalen += (int)strlen(udata);
  3350. }
  3351. /* Open SunLink X.25 socket */
  3352. if (!quiet && *name) {
  3353. printf(" Trying %s... ", name);
  3354. fflush(stdout);
  3355. }
  3356. if ((ttyfd = socket(AF_X25, SOCK_STREAM, 0)) < 0) {
  3357. debug(F101,"netopen socket error","",errno);
  3358. perror ("X.25 socket error");
  3359. return (-1);
  3360. }
  3361. /* Setting X.25 out-of-band data handler */
  3362. pid = getpid();
  3363. if (ioctl(ttyfd,SIOCSPGRP,&pid)) {
  3364. perror("X.25 set process group id error");
  3365. return(-1);
  3366. }
  3367. (VOID) signal(SIGURG,x25oobh);
  3368. /* Set reverse charge call and closed user group if requested */
  3369. bzero ((char *)&x25facil,sizeof(x25facil));
  3370. #ifndef X25_WR_FACILITY
  3371. /* New SunLink (7.0 or 8.0, not sure which)... */
  3372. x25facil.type = T_REVERSE_CHARGE; /* Reverse Charge */
  3373. x25facil.f_reverse_charge = revcall ? 1 : 0;
  3374. if (ioctl(ttyfd,X25_SET_FACILITY,&x25facil) < 0) {
  3375. perror ("Setting X.25 reverse charge");
  3376. return (-1);
  3377. }
  3378. if (closgr > -1) { /* Closed User Group (Outgoing) */
  3379. bzero ((char *)&x25facil,sizeof(x25facil));
  3380. x25facil.type = T_CUG;
  3381. x25facil.f_cug_req = CUG_REQ_ACS;
  3382. x25facil.f_cug_index = closgr;
  3383. if (ioctl(ttyfd,X25_SET_FACILITY,&x25facil) < 0) {
  3384. perror ("Setting X.25 closed user group");
  3385. return (-1);
  3386. }
  3387. }
  3388. #else
  3389. /* Old SunLink 6.0 (or 7.0?)... */
  3390. if (revcall) x25facil.reverse_charge = revcall;
  3391. if (closgr > -1) {
  3392. x25facil.cug_req = 1;
  3393. x25facil.cug_index = closgr;
  3394. }
  3395. if (ioctl(ttyfd,X25_WR_FACILITY,&x25facil) < 0) {
  3396. perror ("Setting X.25 facilities");
  3397. return (-1);
  3398. }
  3399. #endif /* X25_WR_FACILITY */
  3400. /* Need X.25 header with bits Q and M */
  3401. if (ioctl (ttyfd,X25_HEADER,&needh) < 0) {
  3402. perror ("Setting X.25 header");
  3403. return (-1);
  3404. }
  3405. /* Connects to remote host via SunLink X.25 */
  3406. if (connect(ttyfd,(struct sockaddr *)&x25host,sizeof(x25host)) < 0) {
  3407. i = errno;
  3408. debug(F101,"netopen connect errno","",i);
  3409. if (i) {
  3410. perror("netopen x25 connect");
  3411. x25diag();
  3412. }
  3413. (VOID) netclos();
  3414. ttyfd = -1;
  3415. wasclosed = 1;
  3416. ttnproto = NP_NONE;
  3417. errno = i;
  3418. return (-1);
  3419. }
  3420. /* Get X.25 link identification used for the connection */
  3421. if (ioctl(ttyfd,X25_GET_LINK,&linkid) < 0) {
  3422. perror ("Getting X.25 link id");
  3423. return (-1);
  3424. }
  3425. /* Get X.25 logical channel number used for the connection */
  3426. if (ioctl(ttyfd,X25_RD_LCGN,&lcn) < 0) {
  3427. perror ("Getting X.25 lcn");
  3428. return (-1);
  3429. }
  3430. /* Get SunLink X.25 version */
  3431. if (ioctl(ttyfd,X25_VERSION,&x25ver) < 0) {
  3432. perror ("Getting SunLink X.25 version");
  3433. return (-1);
  3434. }
  3435. ttnet = nett; /* Sunlink X.25 network */
  3436. ttnproto = NP_X3; /* PAD X.3, X.28, X.29 protocol */
  3437. if (lcl) if (*lcl < 0) *lcl = 1; /* Local mode */
  3438. return(0);
  3439. } else /* Note that SUNX25 support can coexist with TCP/IP support. */
  3440. #endif /* SUNX25 */
  3441. #ifdef IBMX25
  3442. /* riehm */
  3443. if (nett == NET_IX25) { /* IBM AIX X.25 */
  3444. netclos(); /* Close any previous net connection */
  3445. ttnproto = NP_NONE; /* No protocol selected yet */
  3446. /* find out who we are - this is not so easy on AIX */
  3447. /* riehm: need to write the code that finds this out
  3448. * automatically, or at least allow it to be configured
  3449. * somehow
  3450. */
  3451. if (!local_nua[0] && !x25local_nua(local_nua)) {
  3452. return(-1);
  3453. }
  3454. /* Initialise the X25 API (once per process? once per connection?) */
  3455. debug(F110, "Opening ", x25dev, 0 );
  3456. /* set O_NDELAY to allow polling? */
  3457. if ((ttyfd = open(x25dev, O_RDWR)) < 0) {
  3458. perror ("X.25 device open error");
  3459. debug(F101,"netopen: device open error","",errno);
  3460. return (-1);
  3461. }
  3462. /* push the NPI onto the STREAM */
  3463. if (ioctl(ttyfd,I_PUSH,"npi") < 0 ) {
  3464. close(ttyfd);
  3465. ttyfd = -1;
  3466. wasclosed = 1;
  3467. perror( "kermit: netopen(): couldn't push npi on the X25 stream" );
  3468. debug(F101,"netopen: can't push npi on the X25 stream","",errno);
  3469. return (-1);
  3470. }
  3471. /* set up server mode - bind the x25 port and wait for
  3472. * incoming connections
  3473. */
  3474. if (name[0] == '*') { /* Server */
  3475. /* set up a server - see the warning in x25bind() */
  3476. bind_flags |= TOKEN_REQUEST;
  3477. /* bind kermit to the local X25 address */
  3478. token = x25bind(ttyfd,
  3479. local_nua,
  3480. udata,
  3481. (int)strlen( udata ),
  3482. 1,
  3483. x25port,
  3484. bind_flags
  3485. );
  3486. if (token < 0) {
  3487. debug(F100,"netopen: couldn't bind to local X25 address","",0);
  3488. netclos();
  3489. return(-1);
  3490. }
  3491. /* Currently not connected to a remote host */
  3492. remote_nua[0] = '\0';
  3493. /* store the fd so that incoming calls can have their own fd
  3494. * This is almost support for a true server (ie: a'la ftpd)
  3495. * but we're not quite there yet.
  3496. * used in netclos()
  3497. */
  3498. x25serverfd = ttyfd;
  3499. /*
  3500. * wait for an incoming call
  3501. * this should happen in the "server" command and not in
  3502. * the "set host *" command.
  3503. */
  3504. if ((ttyfd = x25getcall(ttyfd)) < 0) {
  3505. netclos();
  3506. return(-1);
  3507. }
  3508. } else { /* Client */
  3509. /* Bind kermit to the local X25 address */
  3510. token = x25bind(
  3511. ttyfd,
  3512. local_nua,
  3513. (char *)NULL,
  3514. 0,
  3515. 0,
  3516. x25port,
  3517. bind_flags
  3518. );
  3519. if (token < 0) {
  3520. debug(F100,"netopen: couldn't bind to local X25 address","",0);
  3521. netclos();
  3522. return(-1);
  3523. }
  3524. /* riehm: this should be done via the CONNECT command, not HOST! */
  3525. {
  3526. x25serverfd = 0;
  3527. /* call the remote host */
  3528. /* name == address of remote host as char* */
  3529. if (x25call(ttyfd, name, udata) < 0 ) {
  3530. debug(F100,
  3531. "netopen: couldn't connect to remote X25 address",
  3532. "", 0);
  3533. netclos();
  3534. return(-1);
  3535. }
  3536. strcpy(remote_nua, name);
  3537. }
  3538. }
  3539. ttnet = nett; /* AIX X.25 network */
  3540. if (lcl) if (*lcl < 0) *lcl = 1; /* Local mode */
  3541. return(0);
  3542. } else /* Note that IBMX25 support can coexist with TCP/IP support. */
  3543. #endif /* IBMX25 */
  3544. /* Add support for other networks here. */
  3545. if (nett != NET_TCPB) return(-1); /* BSD socket support */
  3546. #ifdef TCPSOCKET
  3547. netclos(); /* Close any previous connection. */
  3548. ckstrncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
  3549. debug(F110,"netopen namecopy",namecopy,0);
  3550. #ifndef NOLISTEN
  3551. if (name[0] == '*')
  3552. return(tcpsrv_open(name, lcl, nett, 0));
  3553. #endif /* NOLISTEN */
  3554. p = namecopy; /* Was a service requested? */
  3555. while (*p != '\0' && *p != ':') p++; /* Look for colon */
  3556. if (*p == ':') { /* Have a colon */
  3557. debug(F110,"netopen name has colon",namecopy,0);
  3558. *p++ = '\0'; /* Get service name or number */
  3559. #ifdef CK_URL
  3560. /*
  3561. Here we have to check for various popular syntaxes:
  3562. host:port (our original syntax)
  3563. URL such as telnet:host or telnet://host/
  3564. Or even telnet://user:password@host:port/path/
  3565. Or a malformed URL such as generated by Netscape 4.0 like:
  3566. telnet:telnet or telnet::host.
  3567. */
  3568. /*
  3569. * REPLACE THIS CODE WITH urlparse() but not on the day of the
  3570. * C-Kermit 8.0 RELEASE.
  3571. */
  3572. if (*p == ':') /* a second colon */
  3573. *p++ = '\0'; /* get rid of that one too */
  3574. while (*p == '/') *p++ = '\0'; /* and slashes */
  3575. x = strlen(p); /* Length of remainder */
  3576. if (p[x-1] == '/') /* If there is a trailing slash */
  3577. p[x-1] = '\0'; /* remove it. */
  3578. debug(F110,"netopen namecopy after stripping",namecopy,0);
  3579. debug(F110,"netopen p after stripping",p,0);
  3580. service = getservbyname(namecopy,"tcp");
  3581. if (service ||
  3582. #ifdef RLOGCODE
  3583. !ckstrcmp("rlogin",namecopy,NAMECPYL,0) ||
  3584. #endif /* RLOGCODE */
  3585. #ifdef CK_SSL
  3586. !ckstrcmp("telnets",namecopy,NAMECPYL,0) ||
  3587. #endif /* CK_SSL */
  3588. !ckstrcmp("iksd",namecopy,NAMECPYL,0)
  3589. ) {
  3590. char temphost[256], tempservice[80], temppath[256];
  3591. char * q = p, *r = p, *w = p;
  3592. int uidfound=0;
  3593. extern char pwbuf[];
  3594. extern int pwflg, pwcrypt;
  3595. if (ttnproto == NP_DEFAULT)
  3596. setnproto(namecopy);
  3597. /* Check for userid and possibly password */
  3598. while (*p != '\0' && *p != '@')
  3599. p++; /* look for @ */
  3600. if (*p == '@') {
  3601. /* found username and perhaps password */
  3602. debug(F110,"netopen namecopy found @","",0);
  3603. *p = '\0';
  3604. p++;
  3605. while (*w != '\0' && *w != ':')
  3606. w++;
  3607. if (*w == ':')
  3608. *w++ = '\0';
  3609. /* r now points to username, save it and the password */
  3610. debug(F110,"netopen namecopy username",r,0);
  3611. debug(F110,"netopen namecopy password",w,0);
  3612. uidfound=1;
  3613. if ( strcmp(uidbuf,r) || *w )
  3614. ckstrncpy(pwbuf,w,PWBUFL+1);
  3615. ckstrncpy(uidbuf,r,UIDBUFLEN);
  3616. pwflg = 1;
  3617. pwcrypt = 0;
  3618. q = p; /* Host after user and pwd */
  3619. } else {
  3620. p = q; /* No username or password */
  3621. }
  3622. /* Now we must look for the optional port. */
  3623. debug(F110,"netopen x p",p,0);
  3624. debug(F110,"netopen x q",q,0);
  3625. /* Look for the port/service or a file/directory path */
  3626. while (*p != '\0' && *p != ':' && *p != '/')
  3627. p++;
  3628. if (*p == ':') {
  3629. debug(F110,"netopen found port",q,0);
  3630. *p++ = '\0'; /* Found a port name or number */
  3631. r = p;
  3632. /* Look for the end of port/service or a file/directory path */
  3633. while (*p != '\0' && *p != '/')
  3634. p++;
  3635. if (*p == '/')
  3636. *p++ = '\0';
  3637. debug(F110,"netopen port",r,0);
  3638. ckstrncpy(tempservice,r,80);
  3639. ckstrncpy(temphost,q,256);
  3640. ckstrncpy(temppath,p,256);
  3641. ckstrncpy(namecopy,temphost,NAMECPYL);
  3642. debug(F110,"netopen tempservice",tempservice,0);
  3643. debug(F110,"netopen temphost",temphost,0);
  3644. debug(F110,"netopen temppath",temppath,0);
  3645. /* move port/service to a buffer that won't go away */
  3646. x = strlen(namecopy);
  3647. p = namecopy + x + 1;
  3648. ckstrncpy(p, tempservice, NAMECPYL - x);
  3649. } else {
  3650. /* Handle a path if we found one */
  3651. if (*p == '/')
  3652. *p++ = '\0';
  3653. ckstrncpy(temppath,p,256);
  3654. /* We didn't find another port, but if q is a service */
  3655. /* then assume that namecopy is actually a host. */
  3656. if (getservbyname(q,"tcp")) {
  3657. p = q;
  3658. } else {
  3659. #ifdef RLOGCODE
  3660. /* rlogin is not a valid service */
  3661. if (!ckstrcmp("rlogin",namecopy,6,0)) {
  3662. ckstrncpy(namecopy,"login",NAMECPYL);
  3663. }
  3664. #endif /* RLOGCODE */
  3665. /* iksd is not a valid service */
  3666. if (!ckstrcmp("iksd",namecopy,6,0)) {
  3667. ckstrncpy(namecopy,"kermit",NAMECPYL);
  3668. }
  3669. /* Reconstruct namecopy */
  3670. ckstrncpy(tempservice,namecopy,80);
  3671. ckstrncpy(temphost,q,256);
  3672. ckstrncpy(namecopy,temphost,NAMECPYL);
  3673. debug(F110,"netopen tempservice",tempservice,0);
  3674. debug(F110,"netopen temphost",temphost,0);
  3675. debug(F110,"netopen temppath",temppath,0);
  3676. /* move port/service to a buffer that won't go away */
  3677. x = strlen(namecopy);
  3678. p = namecopy + x + 1;
  3679. ckstrncpy(p, tempservice, NAMECPYL - x - 1);
  3680. }
  3681. }
  3682. debug(F110,"netopen URL result: host",namecopy,0);
  3683. debug(F110,"netopen URL result: service",p,0);
  3684. debug(F110,"netopen URL result: path",temppath,0);
  3685. #ifdef IKS_GET
  3686. /* If we have set a path specified, we need to try to GET it */
  3687. /* But we have another problem, we have to login first. How */
  3688. /* do we specify that a login must be done before the GET? */
  3689. /* The user's name if specified is in 'userid' and the */
  3690. /* password if any is in 'pwbuf'. */
  3691. if ( temppath[0] ) {
  3692. extern int action;
  3693. extern char * cmarg;
  3694. if ( !uidfound ) {
  3695. /* If no userid was specified as part of the URL but
  3696. * a path was specified, then we
  3697. * set the user name to anonymous and the password
  3698. * to the current userid.
  3699. */
  3700. ckstrncpy(pwbuf,uidbuf,PWBUFL);
  3701. ckstrncat(pwbuf,"@",PWBUFL);
  3702. pwflg = 1;
  3703. pwcrypt = 0;
  3704. ckstrncpy(uidbuf,"anonymous",UIDBUFLEN);
  3705. }
  3706. /*
  3707. * If a file path was specified we perform the GET
  3708. * operation and then terminate the connection.
  3709. *
  3710. * If a directory was given instead of a file, then
  3711. * we should REMOTE CD to the directory and list its
  3712. * contents. But how do we tell the difference?
  3713. */
  3714. makestr(&cmarg,temppath);
  3715. action = 'r';
  3716. }
  3717. #endif /* IKS_GET */
  3718. }
  3719. #endif /* CK_URL */
  3720. } else { /* Otherwise use telnet */
  3721. p = "telnet";
  3722. }
  3723. /*
  3724. By the time we get here, namecopy[] should hold the null-terminated
  3725. hostname or address, and p should point to the service name or number.
  3726. */
  3727. debug(F110,"netopen host",namecopy,0);
  3728. debug(F110,"netopen service requested",p,0);
  3729. /* Use the service port to set the default protocol type if necessary */
  3730. if (ttnproto == NP_DEFAULT)
  3731. setnproto(p);
  3732. ckstrncpy(namecopy2,namecopy,NAMECPYL);
  3733. service = ckgetservice(namecopy,p,namecopy,NAMECPYL);
  3734. if (!service) {
  3735. fprintf(stderr, "Can't find port for service %s\n", p);
  3736. #ifdef TGVORWIN
  3737. debug(F101,"netopen can't get service","",socket_errno);
  3738. #else
  3739. debug(F101,"netopen can't get service","",errno);
  3740. #endif /* TGVORWIN */
  3741. errno = 0; /* (rather than mislead) */
  3742. return(-1);
  3743. } else {
  3744. if (!ckstrcmp(namecopy,namecopy2,-1,0))
  3745. namecopy2[0] = '\0';
  3746. ckstrncpy(svcbuf,ckuitoa(ntohs(service->s_port)),sizeof(svcbuf));
  3747. debug(F110,"netopen service ok",svcbuf,0);
  3748. }
  3749. #ifdef RLOGCODE
  3750. if (service && !strcmp("login",p) && service->s_port != htons(513)) {
  3751. fprintf(stderr,
  3752. " Warning: login service on port %d instead of port 513\n",
  3753. ntohs(service->s_port)
  3754. );
  3755. fprintf(stderr, " Edit SERVICES file if RLOGIN fails to connect.\n");
  3756. debug(F101,"tcpsrv_open login on port","",ntohs(service->s_port));
  3757. }
  3758. #endif /* RLOGCODE */
  3759. #ifndef NOHTTP
  3760. /* For HTTP connections we must preserve the original hostname and */
  3761. /* service requested so we can include them in the Host header. */
  3762. ckmakmsg(http_host_port,sizeof(http_host_port),namecopy,":",
  3763. ckitoa(ntohs(service->s_port)),NULL);
  3764. /* 'namecopy' contains the name of the host to which we want to connect */
  3765. /* 'svcbuf' contains the service name */
  3766. /* 'service->s_port' contains the port number in network byte order */
  3767. /* If we are using an http proxy, we need to create a buffer containing */
  3768. /* hostname:port-number */
  3769. /* to pass to the http_connect() function. Then we need to replace */
  3770. /* 'namecopy' with the name of the proxy server and the service->s_port */
  3771. /* with the port number of the proxy (default port 80). */
  3772. if ( tcp_http_proxy ) {
  3773. ckmakmsg(proxycopy,sizeof(proxycopy),namecopy,":",
  3774. ckuitoa(ntohs(service->s_port)),NULL);
  3775. ckstrncpy(namecopy,tcp_http_proxy,NAMECPYL);
  3776. p = namecopy; /* Was a service requested? */
  3777. while (*p != '\0' && *p != ':') p++; /* Look for colon */
  3778. if (*p == ':') { /* Have a colon */
  3779. debug(F110,"netopen name has colon",namecopy,0);
  3780. *p++ = '\0'; /* Get service name or number */
  3781. } else {
  3782. strcpy(++p,"http");
  3783. }
  3784. service = ckgetservice(namecopy,p,namecopy,NAMECPYL);
  3785. if (!service) {
  3786. fprintf(stderr, "Can't find port for service %s\n", p);
  3787. #ifdef TGVORWIN
  3788. debug(F101,"netopen can't get service for proxy","",socket_errno);
  3789. #else
  3790. debug(F101,"netopen can't get service for proxy","",errno);
  3791. #endif /* TGVORWIN */
  3792. errno = 0; /* (rather than mislead) */
  3793. return(-1);
  3794. }
  3795. ckstrncpy(p,ckuitoa(ntohs(service->s_port)),NAMECPYL-(p-namecopy));
  3796. }
  3797. #endif /* NOHTTP */
  3798. /* Set up socket structure and get host address */
  3799. bzero((char *)&r_addr, sizeof(r_addr));
  3800. debug(F100,"netopen bzero ok","",0);
  3801. /*
  3802. NOTE: Originally the inet_addr() check was #ifdef NT, but is enabled for
  3803. all as of 20 Sep 97, to allow people to "set host" to a specific numeric IP
  3804. address without going through the multihomed host sequence and winding up
  3805. at a different place than the one requested.
  3806. */
  3807. #ifdef INADDR_NONE
  3808. debug(F101,"netopen INADDR_NONE defined","",INADDR_NONE);
  3809. #else /* INADDR_NONE */
  3810. debug(F100,"netopen INADDR_NONE not defined","",0);
  3811. #endif /* INADDR_NONE */
  3812. #ifdef INADDRX
  3813. debug(F100,"netopen INADDRX defined","",0);
  3814. #else /* INADDRX */
  3815. debug(F100,"netopen INADDRX not defined","",0);
  3816. #endif /* INADDRX */
  3817. #ifndef NOMHHOST
  3818. #ifdef INADDRX
  3819. iax = inet_addr(namecopy);
  3820. debug(F111,"netopen inet_addr",namecopy,iax.s_addr);
  3821. #else /* INADDRX */
  3822. #ifdef INADDR_NONE
  3823. iax.s_addr = inet_addr(namecopy);
  3824. debug(F111,"netopen inet_addr",namecopy,iax.s_addr);
  3825. #else /* INADDR_NONE */
  3826. #ifdef SOLARIS
  3827. /* In Solaris inet_addr() is of type in_addr_t which is uint32_t */
  3828. /* (unsigned) yet it returns -1 (signed) on failure. */
  3829. /* It makes a difference in 64-bit builds. */
  3830. rc_inet_addr = inet_addr(namecopy); /* Assign return code to an int */
  3831. iax = (unsigned) rc_inet_addr; /* and from there to whatever.. */
  3832. #else
  3833. #ifndef datageneral
  3834. iax = (unsigned int) inet_addr(namecopy);
  3835. #else
  3836. iax = -1L;
  3837. #endif /* datageneral */
  3838. #endif /* SOLARIS */
  3839. debug(F111,"netopen rc_inet_addr",namecopy,rc_inet_addr);
  3840. debug(F111,"netopen inet_addr",namecopy,iax);
  3841. #endif /* INADDR_NONE */
  3842. #endif /* INADDRX */
  3843. dns = 0;
  3844. if (
  3845. /* This might give warnings on 64-bit platforms but they should be harmless */
  3846. /* because INADDR_NONE should be all 1's anyway, thus the OR part is */
  3847. /* probably superfluous -- not sure why it's even there, maybe it should be */
  3848. /* removed. */
  3849. #ifdef SOLARIS
  3850. rc_inet_addr == -1
  3851. #else
  3852. #ifdef INADDR_NONE
  3853. iax.s_addr == INADDR_NONE /* || iax.s_addr == (unsigned long) -1L */
  3854. #else /* INADDR_NONE */
  3855. iax < 0
  3856. #endif /* INADDR_NONE */
  3857. #endif /* SOLARIS */
  3858. ) {
  3859. if (!quiet) {
  3860. printf(" DNS Lookup... ");
  3861. fflush(stdout);
  3862. }
  3863. if ((host = gethostbyname(namecopy)) != NULL) {
  3864. debug(F110,"netopen gethostbyname != NULL",namecopy,0);
  3865. host = ck_copyhostent(host);
  3866. dns = 1; /* Remember we performed dns lookup */
  3867. r_addr.sin_family = host->h_addrtype;
  3868. if (tcp_rdns && host->h_name && host->h_name[0]
  3869. #ifndef NOHTTP
  3870. && (tcp_http_proxy == NULL)
  3871. #endif /* NOHTTP */
  3872. ) {
  3873. #ifdef COMMENT
  3874. ckstrncpy(xxname,host->h_name,XXNAMELEN);
  3875. debug(F110,"netopen xxname[1]",xxname,0);
  3876. if ((XXNAMELEN - (int)strlen(name)) > ((int)strlen(svcbuf)+1)){
  3877. ckstrncat(xxname,":",XXNAMELEN - (int)strlen(xxname));
  3878. ckstrncat(xxname,svcbuf,XXNAMELEN - (int)strlen(xxname));
  3879. debug(F110,"netopen xxname[2]",xxname,0);
  3880. }
  3881. name = (char *)xxname;
  3882. #else
  3883. ckstrncpy(name,host->h_name,80); /* Bad Bad Bad */
  3884. if ( (80-strlen(name)) > (strlen(svcbuf)+1) ) {
  3885. ckstrncat(name,":",80-strlen(name));
  3886. ckstrncat(name,svcbuf,80-strlen(name));
  3887. }
  3888. #endif /* COMMENT */
  3889. }
  3890. debug(F110,"netopen name after lookup",name,0);
  3891. #ifdef HADDRLIST
  3892. #ifdef h_addr
  3893. /* This is for trying multiple IP addresses - see <netdb.h> */
  3894. if (!(host->h_addr_list))
  3895. return(-1);
  3896. bcopy(host->h_addr_list[0],
  3897. (caddr_t)&r_addr.sin_addr,
  3898. host->h_length
  3899. );
  3900. #else
  3901. bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
  3902. #endif /* h_addr */
  3903. #else /* HADDRLIST */
  3904. #ifdef HPUX6
  3905. r_addr.sin_addr.s_addr = (u_long)host->h_addr;
  3906. #else /* HPUX6 */
  3907. bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
  3908. #endif /* HPUX6 */
  3909. #endif /* HADDRLIST */
  3910. #ifndef HPUX6
  3911. debug(F111,"BCOPY","host->h_length",host->h_length);
  3912. #endif /* HPUX6 */
  3913. }
  3914. }
  3915. #endif /* NOMHHOST */
  3916. debug(F101,"netopen dns","",dns);
  3917. if (!dns) {
  3918. #ifdef INADDRX
  3919. /* inet_addr() is of type struct in_addr */
  3920. struct in_addr ina;
  3921. unsigned long uu;
  3922. debug(F100,"netopen gethostbyname == NULL: INADDRX","",0);
  3923. ina = inet_addr(namecopy);
  3924. uu = *(unsigned int *)&ina;
  3925. #else /* Not INADDRX */
  3926. /* inet_addr() is unsigned long */
  3927. unsigned long uu;
  3928. debug(F100,"netopen gethostbyname == NULL: Not INADDRX","",0);
  3929. uu = inet_addr(namecopy);
  3930. #endif /* INADDRX */
  3931. debug(F101,"netopen uu","",uu);
  3932. if (
  3933. #ifdef INADDR_NONE
  3934. !(uu == INADDR_NONE || uu == (unsigned int) -1L)
  3935. #else /* INADDR_NONE */
  3936. uu != ((unsigned long)-1)
  3937. #endif /* INADDR_NONE */
  3938. ) {
  3939. r_addr.sin_addr.s_addr = uu;
  3940. r_addr.sin_family = AF_INET;
  3941. } else {
  3942. #ifdef VMS
  3943. fprintf(stdout, "\r\n"); /* complete any previous message */
  3944. #endif /* VMS */
  3945. fprintf(stderr, "Can't get address for %s\n", namecopy);
  3946. #ifdef TGVORWIN
  3947. debug(F101,"netopen can't get address","",socket_errno);
  3948. #else
  3949. debug(F101,"netopen can't get address","",errno);
  3950. #endif /* TGVORWIN */
  3951. errno = 0; /* Rather than mislead */
  3952. return(-1);
  3953. }
  3954. }
  3955. /* Get a file descriptor for the connection. */
  3956. r_addr.sin_port = service->s_port;
  3957. ckstrncpy(ipaddr,(char *)inet_ntoa(r_addr.sin_addr),20);
  3958. debug(F110,"netopen trying",ipaddr,0);
  3959. if (!quiet && *ipaddr) {
  3960. printf(" Trying %s... ", ipaddr);
  3961. fflush(stdout);
  3962. }
  3963. /* Loop to try additional IP addresses, if any. */
  3964. do {
  3965. #ifdef EXCELAN
  3966. send_socket.sin_family = AF_INET;
  3967. send_socket.sin_addr.s_addr = 0;
  3968. send_socket.sin_port = 0;
  3969. if ((ttyfd = socket(SOCK_STREAM, (struct sockproto *)0,
  3970. &send_socket, SO_REUSEADDR)) < 0)
  3971. #else /* EXCELAN */
  3972. #ifdef NT
  3973. #ifdef COMMENT_X
  3974. /*
  3975. Must make sure that all sockets are opened in
  3976. Non-overlapped mode since we use the standard
  3977. C RTL functions to read and write data.
  3978. But it doesn't seem to work as planned.
  3979. */
  3980. {
  3981. int optionValue = SO_SYNCHRONOUS_NONALERT;
  3982. if (setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
  3983. (char *) &optionValue, sizeof(optionValue))
  3984. != NO_ERROR)
  3985. return(-1);
  3986. }
  3987. #endif /* COMMENT */
  3988. #endif /* NT */
  3989. if ((ttyfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  3990. #endif /* EXCELAN */
  3991. {
  3992. #ifdef EXCELAN
  3993. experror("TCP socket error");
  3994. #else
  3995. #ifdef VMS
  3996. fprintf(stdout, "\r\n"); /* complete any previous stdout */
  3997. #endif /* VMS */
  3998. #ifdef TGVORWIN
  3999. #ifdef OLD_TWG
  4000. errno = socket_errno;
  4001. #endif /* OLD_TWG */
  4002. socket_perror("TCP socket error");
  4003. debug(F101,"netopen socket error","",socket_errno);
  4004. #else
  4005. perror("TCP socket error");
  4006. debug(F101,"netopen socket error","",errno);
  4007. #endif /* TGVORWIN */
  4008. #endif /* EXCELAN */
  4009. return (-1);
  4010. }
  4011. errno = 0;
  4012. #ifdef RLOGCODE
  4013. /* Not part of the RLOGIN RFC, but the BSD implementation */
  4014. /* requires that the client port be a priviliged port (<1024) */
  4015. /* on a Unix system this would require SuperUser permissions */
  4016. /* thereby saying that the root of the Unix system has given */
  4017. /* permission for this connection to be created */
  4018. if (service->s_port == htons((unsigned short)RLOGIN_PORT)) {
  4019. static unsigned short lport = 1024; /* max reserved port */
  4020. #ifdef OS2
  4021. int s_errno;
  4022. #endif /* OS2 */
  4023. lport--; /* Make sure we do not reuse a port */
  4024. if (lport == 512)
  4025. lport = 1023;
  4026. sin.sin_family = AF_INET;
  4027. if (tcp_address) {
  4028. #ifdef INADDRX
  4029. inaddrx = inet_addr(tcp_address);
  4030. sin.sin_addr.s_addr = *(unsigned long *)&inaddrx;
  4031. #else
  4032. sin.sin_addr.s_addr = inet_addr(tcp_address);
  4033. #endif /* INADDRX */
  4034. } else
  4035. sin.sin_addr.s_addr = INADDR_ANY;
  4036. while (1) {
  4037. sin.sin_port = htons(lport);
  4038. if (bind(ttyfd, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
  4039. break;
  4040. #ifdef OS2
  4041. s_errno = socket_errno;
  4042. if (s_errno && /* OS2 bind fails with 0, if already in use */
  4043. #ifdef NT
  4044. s_errno != WSAEADDRINUSE
  4045. #else
  4046. s_errno != SOCEADDRINUSE &&
  4047. s_errno != (SOCEADDRINUSE - SOCBASEERR)
  4048. #endif /* NT */
  4049. )
  4050. #else /* OS2 */
  4051. #ifdef TGVORWIN
  4052. if (socket_errno != EADDRINUSE)
  4053. #else
  4054. if (errno != EADDRINUSE)
  4055. #endif /* TGVORWIN */
  4056. #endif /* OS2 */
  4057. {
  4058. #ifdef COMMENT
  4059. printf("\nBind failed with errno %d for port %d.\n",
  4060. #ifdef OS2
  4061. s_errno
  4062. #else
  4063. #ifdef TGVORWIN
  4064. socket_errno
  4065. #else
  4066. errno
  4067. #endif /* TGVORWIN */
  4068. #endif /* OS2 */
  4069. , lport
  4070. );
  4071. #ifdef OS2
  4072. debug(F101,"rlogin bind failed","",s_errno);
  4073. #else
  4074. #ifdef TGVORWIN
  4075. debug(F101,"rlogin bind failed","",socket_errno);
  4076. #ifdef OLD_TWG
  4077. errno = socket_errno;
  4078. #endif /* OLD_TWG */
  4079. socket_perror("rlogin bind");
  4080. #else
  4081. debug(F101,"rlogin bind failed","",errno);
  4082. perror("rlogin bind");
  4083. #endif /* TGVORWIN */
  4084. #endif /* OS2 */
  4085. #else /* COMMENT */
  4086. #ifdef OS2
  4087. debug(F101,"rlogin bind s_errno","",s_errno);
  4088. perror("rlogin bind");
  4089. #else
  4090. #ifdef VMS
  4091. printf("\r\n"); /* complete any previous message */
  4092. #endif /* VMS */
  4093. #ifdef TGVORWIN
  4094. debug(F101,"rlogin bind socket_errno","",socket_errno);
  4095. #ifdef OLD_TWG
  4096. errno = socket_errno;
  4097. #endif /* OLD_TWG */
  4098. socket_perror("rlogin bind");
  4099. #else
  4100. debug(F101,"rlogin bind errno","",errno);
  4101. perror("rlogin bind");
  4102. #endif /* TGVORWIN */
  4103. #endif /* OS2 */
  4104. debug(F101,"rlogin local port","",lport);
  4105. #endif /* COMMENT */
  4106. netclos();
  4107. return -1;
  4108. }
  4109. lport--;
  4110. if (lport == 512 /* lowest reserved port to use */ ) {
  4111. printf("\nNo reserved ports available.\n");
  4112. netclos();
  4113. return -1;
  4114. }
  4115. }
  4116. debug(F101,"rlogin lport","",lport);
  4117. ttnproto = NP_RLOGIN;
  4118. } else
  4119. #endif /* RLOGCODE */
  4120. /* If a specific TCP address on the local host is desired we */
  4121. /* must bind it to the socket. */
  4122. #ifndef datageneral
  4123. if (tcp_address) {
  4124. int s_errno;
  4125. debug(F110,"netopen binding socket to",tcp_address,0);
  4126. bzero((char *)&sin,sizeof(sin));
  4127. sin.sin_family = AF_INET;
  4128. #ifdef INADDRX
  4129. inaddrx = inet_addr(tcp_address);
  4130. sin.sin_addr.s_addr = *(unsigned long *)&inaddrx;
  4131. #else
  4132. sin.sin_addr.s_addr = inet_addr(tcp_address);
  4133. #endif /* INADDRX */
  4134. sin.sin_port = 0;
  4135. if (bind(ttyfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
  4136. s_errno = socket_errno; /* Save error code */
  4137. #ifdef TCPIPLIB
  4138. socket_close(ttyfd);
  4139. #else /* TCPIPLIB */
  4140. close(ttyfd);
  4141. #endif /* TCPIPLIB */
  4142. ttyfd = -1;
  4143. wasclosed = 1;
  4144. errno = s_errno; /* and report this error */
  4145. debug(F101,"netopen bind errno","",errno);
  4146. return(-1);
  4147. }
  4148. }
  4149. #endif /* datageneral */
  4150. /* Now connect to the socket on the other end. */
  4151. #ifdef EXCELAN
  4152. if (connect(ttyfd, &r_addr) < 0)
  4153. #else
  4154. #ifdef NT
  4155. WSASafeToCancel = 1;
  4156. #endif /* NT */
  4157. if (connect(ttyfd, (struct sockaddr *)&r_addr, sizeof(r_addr)) < 0)
  4158. #endif /* EXCELAN */
  4159. {
  4160. #ifdef NT
  4161. WSASafeToCancel = 0;
  4162. #endif /* NT */
  4163. #ifdef OS2
  4164. i = socket_errno;
  4165. #else /* OS2 */
  4166. #ifdef TGVORWIN
  4167. i = socket_errno;
  4168. #else
  4169. i = errno; /* Save error code */
  4170. #endif /* TGVORWIN */
  4171. #endif /* OS2 */
  4172. #ifdef RLOGCODE
  4173. if (
  4174. #ifdef OS2
  4175. i && /* OS2 bind fails with 0, if already in use */
  4176. #ifdef NT
  4177. i == WSAEADDRINUSE
  4178. #else
  4179. (i == SOCEADDRINUSE ||
  4180. i == (SOCEADDRINUSE - SOCBASEERR))
  4181. #endif /* NT */
  4182. #else /* OS2 */
  4183. #ifdef TGVORWIN
  4184. socket_errno == EADDRINUSE
  4185. #else
  4186. errno == EADDRINUSE
  4187. #endif /* TGVORWIN */
  4188. #endif /* OS2 */
  4189. && ttnproto == NP_RLOGIN) {
  4190. #ifdef TCPIPLIB
  4191. socket_close(ttyfd); /* Close it. */
  4192. #else
  4193. close(ttyfd);
  4194. #endif /* TCPIPLIB */
  4195. continue; /* Try a different lport */
  4196. }
  4197. #endif /* RLOGCODE */
  4198. #ifdef HADDRLIST
  4199. #ifdef h_addr
  4200. if (host && host->h_addr_list && host->h_addr_list[1]) {
  4201. perror("");
  4202. host->h_addr_list++;
  4203. bcopy(host->h_addr_list[0],
  4204. (caddr_t)&r_addr.sin_addr,
  4205. host->h_length);
  4206. ckstrncpy(ipaddr,(char *)inet_ntoa(r_addr.sin_addr),20);
  4207. debug(F110,"netopen h_addr_list",ipaddr,0);
  4208. if (!quiet && *ipaddr) {
  4209. printf(" Trying %s... ", ipaddr);
  4210. fflush(stdout);
  4211. }
  4212. #ifdef TCPIPLIB
  4213. socket_close(ttyfd); /* Close it. */
  4214. #else
  4215. close(ttyfd);
  4216. #endif /* TCPIPLIB */
  4217. continue;
  4218. }
  4219. #endif /* h_addr */
  4220. #endif /* HADDRLIST */
  4221. netclos();
  4222. ttyfd = -1;
  4223. wasclosed = 1;
  4224. ttnproto = NP_NONE;
  4225. errno = i; /* And report this error */
  4226. #ifdef EXCELAN
  4227. if (errno) experror("netopen connect");
  4228. #else
  4229. #ifdef TGVORWIN
  4230. debug(F101,"netopen connect error","",socket_errno);
  4231. /* if (errno) socket_perror("netopen connect"); */
  4232. #ifdef OLD_TWG
  4233. errno = socket_errno;
  4234. #endif /* OLD_TWG */
  4235. if (!quiet)
  4236. socket_perror("netopen connect");
  4237. #else /* TGVORWIN */
  4238. debug(F101,"netopen connect errno","",errno);
  4239. #ifdef VMS
  4240. if (!quiet)
  4241. perror("\r\nFailed");
  4242. #else
  4243. if (!quiet)
  4244. perror("Failed");
  4245. #endif /* VMS */
  4246. #ifdef DEC_TCPIP
  4247. if (!quiet)
  4248. perror("netopen connect");
  4249. #endif /* DEC_TCPIP */
  4250. #ifdef CMU_TCPIP
  4251. if (!quiet)
  4252. perror("netopen connect");
  4253. #endif /* CMU_TCPIP */
  4254. #endif /* TGVORWIN */
  4255. #endif /* EXCELAN */
  4256. return(-1);
  4257. }
  4258. #ifdef NT
  4259. WSASafeToCancel = 0;
  4260. #endif /* NT */
  4261. isconnect = 1;
  4262. } while (!isconnect);
  4263. #ifdef NON_BLOCK_IO
  4264. on = 1;
  4265. x = socket_ioctl(ttyfd,FIONBIO,&on);
  4266. debug(F101,"netopen FIONBIO","",x);
  4267. #endif /* NON_BLOCK_IO */
  4268. #ifdef NT_TCP_OVERLAPPED
  4269. OverlappedWriteInit();
  4270. OverlappedReadInit();
  4271. #endif /* NT_TCP_OVERLAPPED */
  4272. ttnet = nett; /* TCP/IP (sockets) network */
  4273. #ifndef NOHTTP
  4274. /* We have succeeded in connecting to the HTTP PROXY. So now we */
  4275. /* need to attempt to connect through the proxy to the actual host */
  4276. /* If that is successful, we have to pretend that we made a direct */
  4277. /* connection to the actual host. */
  4278. if ( tcp_http_proxy ) {
  4279. #ifdef OS2
  4280. char * agent = "Kermit 95"; /* Default user agent */
  4281. #else
  4282. char * agent = "C-Kermit";
  4283. #endif /* OS2 */
  4284. if (http_connect(ttyfd,
  4285. tcp_http_proxy_agent ? tcp_http_proxy_agent : agent,
  4286. NULL,
  4287. tcp_http_proxy_user,
  4288. tcp_http_proxy_pwd,
  4289. 0,
  4290. proxycopy
  4291. ) < 0) {
  4292. netclos();
  4293. return(-1);
  4294. }
  4295. ckstrncpy(namecopy,proxycopy,NAMECPYL);
  4296. p = namecopy; /* Was a service requested? */
  4297. while (*p != '\0' && *p != ':') p++; /* Look for colon */
  4298. *p = '\0';
  4299. }
  4300. #endif /* NOHTTP */
  4301. /* Jeff - Does this next block of code that set's the protocol */
  4302. /* need to be here anymore? 5/10/2000 */
  4303. /* There are certain magic port numbers that when used require */
  4304. /* the use of specific protocols. Check this now before we */
  4305. /* set the SO_OOBINLINE state or we might get it wrong. */
  4306. x = ntohs((unsigned short)service->s_port);
  4307. svcnum = x;
  4308. /* See if the service is TELNET. */
  4309. if (x == TELNET_PORT) {
  4310. /* Yes, so if raw port not requested */
  4311. #ifdef COMMENT
  4312. /* Jeff 2005/12/30 */
  4313. if (ttnproto != NP_TCPRAW && ttnproto != NP_SSL_RAW &&
  4314. ttnproto != NP_TLS_RAW && ttnproto != NP_NONE)
  4315. #else
  4316. /* fdc 2005/12/04 */
  4317. if (ttnproto != NP_TCPRAW && ttnproto != NP_NONE)
  4318. #endif /* COMMENT */
  4319. ttnproto = NP_TELNET; /* Select TELNET protocol. */
  4320. }
  4321. #ifdef RLOGCODE
  4322. else if (x == RLOGIN_PORT) {
  4323. ttnproto = NP_RLOGIN;
  4324. }
  4325. #ifdef CK_KERBEROS
  4326. /* There is no good way to do this. If the user didn't tell */
  4327. /* which one to use up front. We may guess wrong if the user */
  4328. /* has both Kerberos versions installed and valid TGTs for each */
  4329. else if (x == KLOGIN_PORT &&
  4330. ttnproto != NP_K4LOGIN &&
  4331. ttnproto != NP_K5LOGIN) {
  4332. if (ck_krb5_is_installed() &&
  4333. ck_krb5_is_tgt_valid())
  4334. ttnproto = NP_K5LOGIN;
  4335. else if (ck_krb4_is_installed() && ck_krb4_is_tgt_valid())
  4336. ttnproto = NP_K4LOGIN;
  4337. else
  4338. ttnproto = NP_K4LOGIN;
  4339. } else if (x == EKLOGIN_PORT &&
  4340. ttnproto != NP_EK4LOGIN &&
  4341. ttnproto != NP_EK5LOGIN) {
  4342. if (ck_krb5_is_installed() && ck_krb5_is_tgt_valid())
  4343. ttnproto = NP_EK5LOGIN;
  4344. else if (ck_krb4_is_installed() && ck_krb4_is_tgt_valid())
  4345. ttnproto = NP_EK4LOGIN;
  4346. else
  4347. ttnproto = NP_EK4LOGIN;
  4348. }
  4349. #endif /* CK_KERBEROS */
  4350. #endif /* RLOGCODE */
  4351. #ifdef IKS_OPTION
  4352. else if (x == KERMIT_PORT) { /* IKS uses Telnet protocol */
  4353. if (ttnproto == NP_NONE)
  4354. ttnproto = NP_KERMIT;
  4355. }
  4356. #endif /* IKS_OPTION */
  4357. #ifdef SO_OOBINLINE
  4358. /*
  4359. The symbol SO_OOBINLINE is not known to Ultrix 2.0.
  4360. It means "leave out of band data inline". The normal value is 0x0100,
  4361. but don't try this on systems where the symbol is undefined.
  4362. */
  4363. /*
  4364. Note from Jeff Altman: 12/13/95
  4365. In implementing rlogin protocol I have come to the conclusion that it is
  4366. a really bad idea to read out-of-band data inline.
  4367. At least Windows and OS/2 does not handle this well.
  4368. And if you need to know that data is out-of-band, then it becomes
  4369. absolutely pointless.
  4370. Therefore, at least on OS2 and Windows (NT) I have changed the value of
  4371. on to 0, so that out-of-band data stays out-of-band.
  4372. 12/18/95
  4373. Actually, OOB data should be read inline when possible. Especially with
  4374. protocols that don't care about the Urgent flag. This is true with Telnet.
  4375. With Rlogin, you need to be able to catch OOB data. However, the best
  4376. way to do this is to set a signal handler on SIGURG. This isn't possible
  4377. on OS/2 and Windows. But it is in UNIX. We will also need OOB data for
  4378. FTP so better create a general mechanism.
  4379. The reason for making OOB data be inline is that the standard ttinc/ttoc
  4380. calls can be used for reading that data on UNIX systems. If we didn't
  4381. have the OOBINLINE option set then we would have to use recv(,MSG_OOB)
  4382. to read it.
  4383. */
  4384. #ifdef RLOGCODE
  4385. #ifdef TCPIPLIB
  4386. if (ttnproto == NP_RLOGIN
  4387. #ifdef CK_KERBEROS
  4388. || ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN
  4389. || ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN
  4390. #endif /* CK_KERBEROS */
  4391. )
  4392. on = 0;
  4393. #else /* TCPIPLIB */
  4394. if (ttnproto == NP_RLOGIN
  4395. #ifdef CK_KERBEROS
  4396. || ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN
  4397. || ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN
  4398. #endif /* CK_KERBEROS */
  4399. ) {
  4400. debug(F100,"Installing rlogoobh on SIGURG","",0);
  4401. signal(SIGURG, rlogoobh);
  4402. on = 0;
  4403. } else {
  4404. debug(F100,"Ignoring SIGURG","",0);
  4405. signal(SIGURG, SIG_DFL);
  4406. }
  4407. #endif /* TCPIPLIB */
  4408. #endif /* RLOGCODE */
  4409. #ifdef datageneral
  4410. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4411. #else
  4412. #ifdef BSD43
  4413. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4414. #else
  4415. #ifdef OSF1
  4416. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4417. #else
  4418. #ifdef POSIX
  4419. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4420. #else
  4421. #ifdef MOTSV88R4
  4422. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4423. #else
  4424. #ifdef SOLARIS
  4425. /*
  4426. Maybe this applies to all SVR4 versions, but the other (else) way has been
  4427. compiling and working fine on all the others, so best not to change it.
  4428. */
  4429. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4430. #else
  4431. #ifdef OSK
  4432. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4433. #else
  4434. #ifdef OS2
  4435. {
  4436. int rc;
  4437. rc = setsockopt(ttyfd,
  4438. SOL_SOCKET,
  4439. SO_OOBINLINE,
  4440. (char *) &on,
  4441. sizeof on
  4442. );
  4443. debug(F111,"setsockopt SO_OOBINLINE",on ? "on" : "off" ,rc);
  4444. }
  4445. #else
  4446. #ifdef VMS /* or, at least, VMS with gcc */
  4447. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4448. #else
  4449. #ifdef CLIX
  4450. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  4451. #else
  4452. setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
  4453. #endif /* CLIX */
  4454. #endif /* VMS */
  4455. #endif /* OS2 */
  4456. #endif /* OSK */
  4457. #endif /* SOLARIS */
  4458. #endif /* MOTSV88R4 */
  4459. #endif /* POSIX */
  4460. #endif /* BSD43 */
  4461. #endif /* OSF1 */
  4462. #endif /* datageneral */
  4463. #endif /* SO_OOBINLINE */
  4464. #ifndef NOTCPOPTS
  4465. #ifndef datageneral
  4466. #ifdef SOL_SOCKET
  4467. #ifdef TCP_NODELAY
  4468. no_delay(ttyfd,tcp_nodelay);
  4469. #endif /* TCP_NODELAY */
  4470. #ifdef SO_KEEPALIVE
  4471. keepalive(ttyfd,tcp_keepalive);
  4472. #endif /* SO_KEEPALIVE */
  4473. #ifdef SO_LINGER
  4474. ck_linger(ttyfd,tcp_linger, tcp_linger_tmo);
  4475. #endif /* SO_LINGER */
  4476. #ifdef SO_SNDBUF
  4477. sendbuf(ttyfd,tcp_sendbuf);
  4478. #endif /* SO_SNDBUF */
  4479. #ifdef SO_RCVBUF
  4480. recvbuf(ttyfd,tcp_recvbuf);
  4481. #endif /* SO_RCVBUF */
  4482. #endif /* SOL_SOCKET */
  4483. #endif /* datageneral */
  4484. #endif /* NOTCPOPTS */
  4485. #ifndef datageneral
  4486. /* Find out our own IP address. */
  4487. /* We need the l_addr structure for [E]KLOGIN. */
  4488. l_slen = sizeof(l_addr);
  4489. bzero((char *)&l_addr, l_slen);
  4490. #ifndef EXCELAN
  4491. if (!getsockname(ttyfd, (struct sockaddr *)&l_addr, &l_slen)) {
  4492. char * s = (char *)inet_ntoa(l_addr.sin_addr);
  4493. ckstrncpy(myipaddr, s, 20);
  4494. debug(F110,"getsockname",myipaddr,0);
  4495. }
  4496. #endif /* EXCELAN */
  4497. #endif /* datageneral */
  4498. /*
  4499. This is really only needed for Kerberos IV but is useful information in any
  4500. case. If we connect to a name that is really a pool, we need to get the
  4501. name of the machine we are actually connecting to for K4 to authenticate
  4502. properly. This way we also update the names properly.
  4503. However, it is a security hole when used with insecure DNS.
  4504. Note: This does not work on Windows 95 or Windows NT 3.5x. This is because
  4505. of the Microsoft implementation of gethostbyaddr() in both Winsock 1.1
  4506. and Winsock 2.0 on those platforms. Their algorithm is:
  4507. 1. Check the HOSTENT cache.
  4508. 2. Check the HOSTS file at %SystemRoot%\System32\DRIVERS\ETC.
  4509. 3. Do a DNS query if the DNS server is configured for name resolution.
  4510. 4. Do an additional NetBIOS remote adapter status to an IP address for its
  4511. NetBIOS name table. This step is specific only to the Windows NT version
  4512. 3.51 implementation.
  4513. The problem is the use of the HOSTENT cache. It means that gethostbyaddr()
  4514. can not be used to resolve the real name of machine if it was originally
  4515. accessed by an alias used to represent a cluster.
  4516. */
  4517. if ((tcp_rdns && dns || tcp_rdns == SET_ON
  4518. #ifdef CK_KERBEROS
  4519. || tcp_rdns == SET_AUTO &&
  4520. (ck_krb5_is_installed() || ck_krb4_is_installed())
  4521. #endif /* CK_KERBEROS */
  4522. )
  4523. #ifndef NOHTTP
  4524. && (tcp_http_proxy == NULL)
  4525. #endif /* NOHTTP */
  4526. #ifdef CK_SSL
  4527. && !(ssl_only_flag || tls_only_flag)
  4528. #endif /* CK_SSL */
  4529. ) {
  4530. #ifdef NT
  4531. if (isWin95())
  4532. sleep(1);
  4533. #endif /* NT */
  4534. if (!quiet) {
  4535. printf(" Reverse DNS Lookup... ");
  4536. fflush(stdout);
  4537. }
  4538. if (host = gethostbyaddr((char *)&r_addr.sin_addr,4,PF_INET)) {
  4539. char * s;
  4540. host = ck_copyhostent(host);
  4541. debug(F100,"netopen gethostbyname != NULL","",0);
  4542. if (!quiet) {
  4543. printf("(OK)\n");
  4544. fflush(stdout);
  4545. }
  4546. s = host->h_name;
  4547. if (!s) { /* This can happen... */
  4548. debug(F100,"netopen host->h_name is NULL","",0);
  4549. s = "";
  4550. }
  4551. /* Something is wrong with inet_ntoa() on HPUX 10.xx */
  4552. /* The compiler says "Integral value implicitly converted to */
  4553. /* pointer in assignment." The prototype is right there */
  4554. /* in <arpa/inet.h> so what's the problem? */
  4555. /* Ditto in HP-UX 5.x, but not 8.x or 9.x... */
  4556. if (!*s) { /* No name so substitute the address */
  4557. debug(F100,"netopen host->h_name is empty","",0);
  4558. s = inet_ntoa(r_addr.sin_addr); /* Convert address to string */
  4559. if (!s) /* Trust No 1 */
  4560. s = "";
  4561. if (*s) { /* If it worked, use this string */
  4562. ckstrncpy(ipaddr,s,20);
  4563. }
  4564. s = ipaddr; /* Otherwise stick with the IP */
  4565. if (!*s) /* or failing that */
  4566. s = namecopy; /* the name we were called with. */
  4567. }
  4568. if (*s) { /* Copying into our argument? */
  4569. ckstrncpy(name,s,80); /* Bad Bad Bad */
  4570. if ( (80-strlen(name)) > (strlen(svcbuf)+1) ) {
  4571. ckstrncat(name,":",80-strlen(name));
  4572. ckstrncat(name,svcbuf,80-strlen(name));
  4573. }
  4574. }
  4575. if (!quiet && *s
  4576. #ifndef NOICP
  4577. && !doconx
  4578. #endif /* NOICP */
  4579. ) {
  4580. printf(" %s connected on port %s\n",s,p);
  4581. #ifdef BETADEBUG
  4582. /* This is simply for testing the DNS entries */
  4583. if (host->h_aliases) {
  4584. char ** a = host->h_aliases;
  4585. while (*a) {
  4586. printf(" alias => %s\n",*a);
  4587. a++;
  4588. }
  4589. }
  4590. #endif /* BETADEBUG */
  4591. }
  4592. } else {
  4593. if (!quiet) printf("Failed.\n");
  4594. }
  4595. } else if (!quiet) printf("(OK)\n");
  4596. if (!quiet) fflush(stdout);
  4597. /* This should already have been done but just in case */
  4598. ckstrncpy(ipaddr,(char *)inet_ntoa(r_addr.sin_addr),20);
  4599. #ifdef CK_SECURITY
  4600. /* Before Initialization Telnet/Rlogin Negotiations Init Kerberos */
  4601. #ifndef NOHTTP
  4602. if (tcp_http_proxy) {
  4603. for (i=strlen(proxycopy); i >= 0 ; i--)
  4604. if ( proxycopy[i] == ':' )
  4605. proxycopy[i] = '\0';
  4606. }
  4607. #endif /* NOHTTP */
  4608. ck_auth_init(
  4609. #ifndef NOHTTP
  4610. tcp_http_proxy ? proxycopy :
  4611. #endif /* NOHTTP */
  4612. (tcp_rdns && host && host->h_name && host->h_name[0]) ?
  4613. (char *)host->h_name : (namecopy2[0] ? namecopy2 :
  4614. (namecopy[0] ? namecopy : ipaddr)),
  4615. ipaddr,
  4616. uidbuf,
  4617. ttyfd
  4618. );
  4619. #endif /* CK_SECURITY */
  4620. #ifdef CK_SSL
  4621. if (ck_ssleay_is_installed()) {
  4622. if (!ssl_tn_init(SSL_CLIENT)) {
  4623. debug(F100,"netopen ssl_tn_init() failed","",0);
  4624. if (bio_err!=NULL) {
  4625. BIO_printf(bio_err,"ssl_tn_init() failed\n");
  4626. ERR_print_errors(bio_err);
  4627. } else {
  4628. fflush(stderr);
  4629. fprintf(stderr,"ssl_tn_init() failed\n");
  4630. ERR_print_errors_fp(stderr);
  4631. }
  4632. if (tls_only_flag || ssl_only_flag) {
  4633. debug(F100,"netopen ssl/tls required","",0);
  4634. netclos();
  4635. return(-1);
  4636. }
  4637. /* we will continue to accept the connection */
  4638. /* without SSL or TLS support unless required. */
  4639. if ( TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) != TN_NG_MU )
  4640. TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
  4641. if ( TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) != TN_NG_MU )
  4642. TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  4643. if ( TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) != TN_NG_MU )
  4644. TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
  4645. if ( TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) != TN_NG_MU )
  4646. TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  4647. } else if ( ck_ssl_outgoing(ttyfd) < 0 ) {
  4648. debug(F100,"ck_ssl_outgoing() failed","",0);
  4649. netclos();
  4650. return(-1);
  4651. }
  4652. }
  4653. #endif /* CK_SSL */
  4654. #ifdef RLOGCODE
  4655. if (ttnproto == NP_RLOGIN
  4656. #ifdef CK_KERBEROS
  4657. || ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN
  4658. || ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN
  4659. #endif /* CK_KERBEROS */
  4660. ) { /* Similar deal for rlogin */
  4661. if (rlog_ini(((tcp_rdns && host && host->h_name && host->h_name[0]) ?
  4662. (CHAR *)host->h_name : (CHAR *)ipaddr),
  4663. service->s_port,
  4664. &l_addr,&r_addr
  4665. ) < 0) {
  4666. debug(F100,"rlogin initialization failed","",0);
  4667. netclos();
  4668. return(-1);
  4669. }
  4670. } else
  4671. #endif /* RLOGCODE */
  4672. if (tn_ini() < 0) { /* Start Telnet negotiations. */
  4673. netclos();
  4674. return(-1); /* Gone, so open failed. */
  4675. }
  4676. if (ttchk() < 0) {
  4677. netclos();
  4678. return(-1);
  4679. }
  4680. #ifdef CK_KERBEROS
  4681. #ifdef KRB5_U2U
  4682. if ( ttnproto == NP_K5U2U ) {
  4683. if (k5_user_to_user_client_auth()) {
  4684. netclos();
  4685. return(-1);
  4686. }
  4687. }
  4688. #endif /* KRB5_U2U */
  4689. #endif /* CK_KERBEROS */
  4690. debug(F101,"netopen service","",svcnum);
  4691. debug(F110,"netopen name",name,0);
  4692. debug(F110,"netopen ipaddr",ipaddr,0);
  4693. ckstrncpy(hostipaddr,ipaddr,63);
  4694. if (lcl) if (*lcl < 0) /* Local mode. */
  4695. *lcl = 1;
  4696. #endif /* TCPSOCKET */
  4697. return(0); /* Done. */
  4698. }
  4699. /* N E T C L O S -- Close current network connection. */
  4700. #ifndef NOLOCAL
  4701. _PROTOTYP(VOID slrestor,(VOID));
  4702. #ifdef CK_SSL
  4703. int tls_norestore = 0;
  4704. #endif /* CK_SSL */
  4705. #endif /* NOLOCAL */
  4706. int
  4707. netclos() {
  4708. static int close_in_progress = 0;
  4709. int x = 0, y, z;
  4710. debug(F101,"netclos","",ttyfd);
  4711. #ifdef NETLEBUF
  4712. if (!tt_push_inited)
  4713. le_init();
  4714. #endif /* NETLEBUF */
  4715. if (ttyfd == -1) /* Was open? */
  4716. return(0); /* Wasn't. */
  4717. if (close_in_progress)
  4718. return(0);
  4719. close_in_progress = 1; /* Remember */
  4720. #ifndef NOLOCAL
  4721. /* This function call should not be here since this is a direct call */
  4722. /* from an I/O routine to a user interface level function. However, */
  4723. /* the reality is that we do not have pure interfaces. If we ever */
  4724. /* decide to clean this up the UI level should assign this function */
  4725. /* via a pointer assignment. - Jeff 9/10/1999 */
  4726. #ifdef CK_SSL
  4727. if (!tls_norestore)
  4728. #endif /* CK_SSL */
  4729. slrestor();
  4730. #endif /* NOLOCAL */
  4731. #ifdef OS2
  4732. RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
  4733. #else /* OS2 */
  4734. if (ttyfd > -1) /* Was. */
  4735. #endif /* OS2 */
  4736. {
  4737. #ifdef VMS
  4738. y = 1; /* Turn on nonblocking reads */
  4739. z = socket_ioctl(ttyfd,FIONBIO,&y);
  4740. debug(F111,"netclos FIONBIO","on",z);
  4741. #endif /* VMS */
  4742. #ifdef TNCODE
  4743. if (ttnproto == NP_TELNET) {
  4744. if (!TELOPT_ME(TELOPT_LOGOUT)
  4745. #ifdef COMMENT
  4746. /* Jeff 2005/12/30 */
  4747. #ifdef CK_SSL
  4748. && !ssl_raw_flag && !tls_raw_flag
  4749. #endif /* CK_SSL */
  4750. #endif /* COMMENT */
  4751. ) {
  4752. /* Send LOGOUT option before close */
  4753. if (tn_sopt(DO,TELOPT_LOGOUT) >= 0) {
  4754. TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
  4755. /* It would be nice to call tn_wait but we can't */
  4756. }
  4757. }
  4758. tn_push(); /* Place any waiting data into input*/
  4759. }
  4760. #endif /* TNCODE */
  4761. #ifdef CK_SSL
  4762. if (ssl_active_flag) {
  4763. if (ssl_debug_flag)
  4764. BIO_printf(bio_err,"calling SSL_shutdown\n");
  4765. SSL_shutdown(ssl_con);
  4766. ssl_active_flag = 0;
  4767. }
  4768. if (tls_active_flag) {
  4769. if (ssl_debug_flag)
  4770. BIO_printf(bio_err,"calling SSL_shutdown\n");
  4771. SSL_shutdown(tls_con);
  4772. tls_active_flag = 0;
  4773. }
  4774. #endif /* CK_SSL */
  4775. #ifdef VMS
  4776. ck_cancio(); /* Cancel any outstanding reads. */
  4777. #endif /* VMS */
  4778. #ifdef TCPIPLIB
  4779. x = socket_close(ttyfd); /* Close it. */
  4780. #else
  4781. #ifndef OS2
  4782. #ifdef IBMX25
  4783. if (ttnet == NET_IX25) {
  4784. /* riehm: should send a disc_req - but only if link is still OK */
  4785. x = x25clear();
  4786. close(ttyfd);
  4787. if (x25serverfd) {
  4788. /* we were the passive client of a server, now we
  4789. * go back to being the normal client.
  4790. * I hope that kermit can cope with the logic that
  4791. * there can still be a connection after netclos
  4792. * has been called.
  4793. */
  4794. ttyfd = x25serverfd;
  4795. x25serverfd = 0;
  4796. /*
  4797. * need to close the server connection too - because
  4798. * all file descriptors connected to the NPI have the
  4799. * same status.
  4800. *
  4801. * The problem is that any waiting connections get
  4802. * lost, the client doesn't realise, and hangs.
  4803. */
  4804. netclos();
  4805. }
  4806. x25_state = X25_CLOSED; /* riehm: dead code? */
  4807. } else
  4808. #endif /* IBMX25 */
  4809. x = close(ttyfd);
  4810. #endif /* OS2 */
  4811. #endif /* TCPIPLIB */
  4812. }
  4813. ttyfd = -1; /* Mark it as closed. */
  4814. wasclosed = 1;
  4815. #ifdef OS2
  4816. ReleaseTCPIPMutex();
  4817. #endif /* OS2 */
  4818. #ifdef TNCODE
  4819. #ifdef CK_FORWARD_X
  4820. fwdx_close_all(); /* Shut down any Forward X sockets */
  4821. #endif /* CK_FORWARD_X */
  4822. tn_reset(); /* The Reset Telnet Option table. */
  4823. debug(F100,"netclose setting tn_init = 0","",0);
  4824. tn_init = 0; /* Remember about telnet protocol... */
  4825. sstelnet = 0; /* Client-side Telnet */
  4826. #endif /* TNCODE */
  4827. *ipaddr = '\0'; /* Zero the IP address string */
  4828. tcp_incoming = 0; /* No longer incoming */
  4829. /* Don't reset ttnproto so that we can remember which protocol is in use */
  4830. #ifdef TCPIPLIB
  4831. /*
  4832. Empty the internal buffers so they won't be used as invalid input on
  4833. the next connect attempt (rlogin).
  4834. */
  4835. ttibp = 0;
  4836. ttibn = 0;
  4837. #endif /* TCPIPLIB */
  4838. #ifdef CK_KERBEROS
  4839. /* If we are automatically destroying Kerberos credentials on Close */
  4840. /* do it now. */
  4841. #ifdef KRB4
  4842. if (krb4_autodel == KRB_DEL_CL) {
  4843. extern struct krb_op_data krb_op;
  4844. krb_op.version = 4;
  4845. krb_op.cache = NULL;
  4846. ck_krb4_destroy(&krb_op);
  4847. }
  4848. #endif /* KRB4 */
  4849. #ifdef KRB5
  4850. if (krb5_autodel == KRB_DEL_CL) {
  4851. extern struct krb_op_data krb_op;
  4852. extern char * krb5_d_cc;
  4853. krb_op.version = 5;
  4854. krb_op.cache = krb5_d_cc;
  4855. ck_krb5_destroy(&krb_op);
  4856. }
  4857. #endif /* KRB5 */
  4858. #endif /* CK_KERBEROS */
  4859. close_in_progress = 0; /* Remember we are done. */
  4860. return(x);
  4861. }
  4862. #ifdef OS2
  4863. int
  4864. os2socketerror( int s_errno ) {
  4865. #ifdef OS2ONLY
  4866. if (s_errno > 0 && s_errno <= SOCBASEERR) {
  4867. /* in OS/2, there is a problem with threading in that
  4868. * the value of errno is not thread safe. It can be
  4869. * set to a value from a previous library call and if
  4870. * it was not cleared it will appear here. Only treat
  4871. * valid socket error codes as errors in this function.
  4872. */
  4873. debug(F100,"os2socketerror errno.h","",0);
  4874. socket_errno = 0;
  4875. return(0);
  4876. }
  4877. #endif /* OS2ONLY */
  4878. switch (s_errno) {
  4879. case 0: /* NO ERROR */
  4880. debug(F100,"os2socketerror NOERROR","",0);
  4881. return(0);
  4882. #ifdef NT
  4883. case WSAECONNRESET:
  4884. #else /* NT */
  4885. case SOCECONNRESET:
  4886. case SOCECONNRESET - SOCBASEERR:
  4887. #endif /* NT */
  4888. debug(F100,"os2socketerror ECONRESET","",0);
  4889. tn_debug("ECONRESET");
  4890. netclos(); /* *** *** */
  4891. return(-1); /* Connection is broken. */
  4892. #ifdef NT
  4893. case WSAECONNABORTED:
  4894. #else /* NT */
  4895. case SOCECONNABORTED:
  4896. case SOCECONNABORTED - SOCBASEERR:
  4897. #endif /* NT */
  4898. debug(F100,"os2socketerror ECONNABORTED","",0);
  4899. tn_debug("ECONNABORTED");
  4900. netclos(); /* *** *** */
  4901. return(-1); /* Connection is broken. */
  4902. #ifdef NT
  4903. case WSAENETRESET:
  4904. #else /* NT */
  4905. case SOCENETRESET:
  4906. case SOCENETRESET - SOCBASEERR:
  4907. #endif /* NT */
  4908. debug(F100,"os2socketerror ENETRESET","",0);
  4909. tn_debug("ENETRESET");
  4910. netclos(); /* *** *** */
  4911. return(-1); /* Connection is broken. */
  4912. #ifdef NT
  4913. case WSAENOTCONN:
  4914. #else /* NT */
  4915. case SOCENOTCONN:
  4916. case SOCENOTCONN - SOCBASEERR:
  4917. #endif /* NT */
  4918. debug(F100,"os2socketerror ENOTCONN","",0);
  4919. tn_debug("ENOTCONN");
  4920. netclos(); /* *** *** */
  4921. return(-1); /* Connection is broken. */
  4922. #ifdef NT
  4923. case WSAESHUTDOWN:
  4924. debug(F100,"os2socketerror ESHUTDOWN","",0);
  4925. tn_debug("ESHUTDOWN");
  4926. netclos(); /* *** *** */
  4927. return(-1); /* Connection is broken. */
  4928. #endif /* NT */
  4929. #ifdef NT
  4930. case WSAEWOULDBLOCK:
  4931. #else
  4932. case SOCEWOULDBLOCK:
  4933. case SOCEWOULDBLOCK - SOCBASEERR:
  4934. #endif /* NT */
  4935. debug(F100,"os2socketerror EWOULDBLOCK","",0);
  4936. return(0);
  4937. #ifdef NT
  4938. case ERROR_IO_INCOMPLETE:
  4939. case ERROR_IO_PENDING:
  4940. case ERROR_OPERATION_ABORTED:
  4941. return(0);
  4942. #endif /* NT */
  4943. default:
  4944. return(-2);
  4945. }
  4946. return(0);
  4947. }
  4948. #endif /* OS2 */
  4949. /* N E T T C H K -- Check if network up, and how many bytes can be read */
  4950. /*
  4951. Returns number of bytes waiting, or -1 if connection has been dropped.
  4952. */
  4953. int /* Check how many bytes are ready */
  4954. nettchk() { /* for reading from network */
  4955. #ifdef TCPIPLIB
  4956. long count = 0;
  4957. int x = 0, z;
  4958. long y;
  4959. char c;
  4960. int rc;
  4961. #ifdef NT
  4962. extern int ionoblock; /* For Overlapped I/O */
  4963. #endif /* NT */
  4964. debug(F101,"nettchk entry ttibn","",ttibn);
  4965. debug(F101,"nettchk entry ttibp","",ttibp);
  4966. #ifdef NETLEBUF
  4967. {
  4968. int n = 0;
  4969. if (ttpush >= 0)
  4970. n++;
  4971. n += le_inbuf();
  4972. if (n > 0)
  4973. return(n);
  4974. }
  4975. #endif /* NETLEBUF */
  4976. #ifndef OS2
  4977. #ifndef BEBOX
  4978. socket_errno = 0; /* This is a function call in NT, and BeOS */
  4979. #endif /* BEBOX */
  4980. #endif /* OS2 */
  4981. if (ttyfd == -1) {
  4982. debug(F100,"nettchk socket is closed","",0);
  4983. return(-1);
  4984. }
  4985. /*
  4986. Note: this socket_ioctl() call does NOT return an error if the
  4987. connection has been broken. (At least not in MultiNet.)
  4988. */
  4989. #ifdef COMMENT
  4990. /* Another trick that can be tried here is something like this: */
  4991. if (ttnet == NET_TCPB) {
  4992. char dummy;
  4993. x = read(ttyfd,&dummy,0); /* Try to read nothing */
  4994. if (x < 0) { /* "Connection reset by peer" */
  4995. perror("TCP/IP"); /* or somesuch... */
  4996. ttclos(0); /* Close our end too. */
  4997. return(-1);
  4998. }
  4999. }
  5000. #endif /* COMMENT */
  5001. #ifdef CK_SSL
  5002. if (ssl_active_flag) {
  5003. #ifndef IKSDONLY
  5004. #ifdef OS2
  5005. if ( IsConnectMode() ) {
  5006. debug(F101,"nettchk (ssl_active_flag) returns","",count);
  5007. return(0);
  5008. }
  5009. #endif /* OS2 */
  5010. #endif /* IKSDONLY */
  5011. count = SSL_pending(ssl_con);
  5012. if (count < 0) {
  5013. debug(F111,"nettchk","SSL_pending error",count);
  5014. netclos();
  5015. return(-1);
  5016. }
  5017. if ( count > 0 )
  5018. return(count); /* Don't perform a read */
  5019. } else if (tls_active_flag) {
  5020. #ifndef IKSDONLY
  5021. #ifdef OS2
  5022. if ( IsConnectMode() ) {
  5023. debug(F101,"nettchk (tls_active_flag) returns","",count);
  5024. return(0);
  5025. }
  5026. #endif /* OS2 */
  5027. #endif /* IKSDONLY */
  5028. count = SSL_pending(tls_con);
  5029. if (count < 0) {
  5030. debug(F111,"nettchk","TLS_pending error",count);
  5031. netclos();
  5032. return(-1);
  5033. }
  5034. if ( count > 0 )
  5035. return(count); /* Don't perform a read */
  5036. } else
  5037. #endif /* CK_SSL */
  5038. if (socket_ioctl(ttyfd,FIONREAD,
  5039. #ifdef COMMENT
  5040. /* Now we've changed the ioctl(..,..,x) prototype for DECC to (void *) */
  5041. #ifdef __DECC
  5042. /* NOTE: "&count" might need to be "(char *)&count" in some settings. */
  5043. /* Cast needed for DECC 4.1 & later? */
  5044. /* Maybe, but __DECC_VER only exists in 5.0 and later */
  5045. (char *)
  5046. #endif /* __DECC */
  5047. #endif /* COMMENT */
  5048. &count
  5049. ) < 0) {
  5050. debug(F101,"nettchk socket_ioctl error","",socket_errno);
  5051. /* If the connection is gone, the connection is gone. */
  5052. netclos();
  5053. #ifdef NT_TCP_OVERLAPPED
  5054. /* Is there anything in the overlapped I/O buffers? */
  5055. count += OverlappedDataWaiting();
  5056. #endif /* NT_TCP_OVERLAPPED */
  5057. count += ttibn;
  5058. return(count>0?count:-1);
  5059. }
  5060. debug(F101,"nettchk count","",count);
  5061. #ifdef NT_TCP_OVERLAPPED
  5062. /* Is there anything in the overlapped I/O buffers? */
  5063. count += OverlappedDataWaiting();
  5064. debug(F101,"nettchk count w/overlapped","",count);
  5065. #endif /* NT_TCP_OVERLAPPED */
  5066. #ifdef OS2
  5067. #ifndef IKSDONLY
  5068. if ( IsConnectMode() ) {
  5069. debug(F101,"nettchk (FIONREAD) returns","",count);
  5070. return(count);
  5071. }
  5072. #endif /* IKSDONLY */
  5073. #endif /* OS2 */
  5074. /* For the sake of efficiency, if there is still data in the ttibuf */
  5075. /* do not go to the bother of checking to see of the connection is */
  5076. /* still valid. The handle is still good, so just return the count */
  5077. /* of the bytes that we already have left to process. */
  5078. #ifdef OS2
  5079. if ( count > 0 || ttibn > 0 ) {
  5080. count+=ttibn;
  5081. debug(F101,"nettchk (count+ttibn > 0) returns","",count);
  5082. return(count);
  5083. } else {
  5084. RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
  5085. if ( ttibn == 0 )
  5086. ttibp = 0; /* reset for next read */
  5087. }
  5088. #else /* OS2 */
  5089. if ( count > 0 || ttibn > 0 ) {
  5090. debug(F101,"nettchk returns","",count+ttibn);
  5091. return(count+ttibn);
  5092. }
  5093. ttibn = ttibp = 0;
  5094. #endif /* OS2 */
  5095. /*
  5096. The following code works well in most settings, but messes things up in
  5097. others, including CMU/Tek TCP/IP and UCX 2.0, where it somehow manages to
  5098. make it impossible to ever make a new connection to the same host again with
  5099. CONNECT, once it has been logged out from the first time. Not even if you
  5100. HANGUP first, or SET HOST<CR>, or SET LINE<CR>. Reportedly, however, it
  5101. does work OK in later releases of UCX. But there is no way we can
  5102. accommodate both old and new -- we might have static linking or dynamic
  5103. linking, etc etc. If we have static, I only have access to 2.0, where this
  5104. doesn't work, etc etc blah blah.
  5105. In the following lines, we define a symbol NOCOUNT for builds where we want
  5106. to omit this code. By default, it is omitted for CMU/Tek. You can force
  5107. omission of it for other combinations by defining NOCOUNT in CFLAGS. You
  5108. can force inclusion of this code, even for CMU/Tek, by including NONOCOUNT
  5109. in CFLAGS.
  5110. */
  5111. #ifdef NONOCOUNT
  5112. #ifdef NOCOUNT
  5113. #undef NOCOUNT
  5114. #endif /* NOCOUNT */
  5115. #else
  5116. #ifndef NOCOUNT
  5117. #ifdef CMU_TCPIP
  5118. #define NOCOUNT
  5119. #endif /* CMU_TCPIP */
  5120. #endif /* NOCOUNT */
  5121. #endif /* NONOCOUNT */
  5122. /* From this point forward we have a possible race condition in K95
  5123. * due to its use of multiple threads. Therefore, we must ensure
  5124. * that only one thread attempt to read/write from the socket at a
  5125. * time. Otherwise, it is possible for a buffer to be overwritten.
  5126. */
  5127. /* we know now that count >= 0 and that ttibn == 0 */
  5128. if (count == 0
  5129. #ifdef RLOGCODE
  5130. #ifdef CK_KERBEROS
  5131. && ttnproto != NP_EK4LOGIN && ttnproto != NP_EK5LOGIN
  5132. #endif /* CK_KERBEROS */
  5133. #endif /* RLOGCODE */
  5134. ) {
  5135. int s_errno = 0;
  5136. #ifndef NOCOUNT
  5137. /*
  5138. Here we need to tell the difference between a 0 count on an active
  5139. connection, and a 0 count because the remote end of the socket broke the
  5140. connection. There is no mechanism in TGV MultiNet (or WIN/TCP?) to query
  5141. the status of the connection, so we have to do a read. -1 means there was
  5142. no data available (socket_errno == EWOULDBLOCK), 0 means the connection is
  5143. down. But if, by chance, we actually get a character, we have to put it
  5144. where it won't be lost.
  5145. */
  5146. #ifndef NON_BLOCK_IO
  5147. #ifdef OS2
  5148. #ifdef CK_SSL
  5149. RequestSSLMutex(SEM_INDEFINITE_WAIT);
  5150. #endif /* CK_SSL */
  5151. #endif /* OS2 */
  5152. y = 1; /* Turn on nonblocking reads */
  5153. z = socket_ioctl(ttyfd,FIONBIO,&y);
  5154. debug(F111,"nettchk FIONBIO","on",z);
  5155. #ifdef OS2
  5156. #ifdef CK_SSL
  5157. ReleaseSSLMutex();
  5158. #endif /* CK_SSL */
  5159. #endif /* OS2 */
  5160. #endif /* NON_BLOCK_IO */
  5161. #ifdef NT_TCP_OVERLAPPED
  5162. ionoblock = 1; /* For Overlapped I/O */
  5163. #endif /* NT_TCP_OVERLAPPED */
  5164. #ifdef CK_SSL
  5165. if ( ssl_active_flag || tls_active_flag ) {
  5166. #ifdef OS2
  5167. ssl_read:
  5168. x = SSL_read( ssl_active_flag?ssl_con:tls_con,
  5169. &ttibuf[ttibp+ttibn],
  5170. TTIBUFL-ttibp-ttibn );
  5171. switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
  5172. case SSL_ERROR_NONE:
  5173. debug(F111,"nettchk SSL_ERROR_NONE","x",x);
  5174. break;
  5175. case SSL_ERROR_WANT_WRITE:
  5176. debug(F100,"nettchk SSL_ERROR_WANT_WRITE","",0);
  5177. x = -1;
  5178. break;
  5179. case SSL_ERROR_WANT_READ:
  5180. debug(F100,"nettchk SSL_ERROR_WANT_READ","",0);
  5181. x = -1;
  5182. break;
  5183. case SSL_ERROR_SYSCALL:
  5184. if ( x == 0 ) { /* EOF */
  5185. netclos();
  5186. rc = -1;
  5187. goto nettchk_return;
  5188. } else {
  5189. #ifdef NT
  5190. int gle = GetLastError();
  5191. #endif /* NT */
  5192. #ifndef NON_BLOCK_IO
  5193. #ifdef OS2
  5194. #ifdef CK_SSL
  5195. RequestSSLMutex(SEM_INDEFINITE_WAIT);
  5196. #endif /* CK_SSL */
  5197. #endif /* OS2 */
  5198. y = 0; /* Turn off nonblocking reads */
  5199. z = socket_ioctl(ttyfd,FIONBIO,&y);
  5200. debug(F111,"nettchk FIONBIO","off",z);
  5201. #ifdef OS2
  5202. #ifdef CK_SSL
  5203. ReleaseSSLMutex();
  5204. #endif /* CK_SSL */
  5205. #endif /* OS2 */
  5206. #endif /* NON_BLOCK_IO */
  5207. #ifdef NT_TCP_OVERLAPPED
  5208. ionoblock = 0; /* For Overlapped I/O */
  5209. #endif /* NT_TCP_OVERLAPPED */
  5210. #ifdef NT
  5211. debug(F111,"nettchk SSL_ERROR_SYSCALL",
  5212. "GetLastError()",gle);
  5213. rc = os2socketerror(gle);
  5214. if (rc == -1)
  5215. rc = -2;
  5216. else if ( rc == -2 )
  5217. rc = -1;
  5218. goto nettchk_return;
  5219. #endif /* NT */
  5220. break;
  5221. }
  5222. case SSL_ERROR_WANT_X509_LOOKUP:
  5223. debug(F100,"nettchk SSL_ERROR_WANT_X509_LOOKUP","",0);
  5224. break;
  5225. case SSL_ERROR_SSL:
  5226. if (bio_err!=NULL) {
  5227. int len;
  5228. extern char ssl_err[];
  5229. BIO_printf(bio_err,"nettchk() SSL_ERROR_SSL\n");
  5230. ERR_print_errors(bio_err);
  5231. len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
  5232. ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
  5233. debug(F110,"nettchk SSL_ERROR_SSL",ssl_err,0);
  5234. if (ssl_debug_flag)
  5235. printf(ssl_err);
  5236. } else if (ssl_debug_flag) {
  5237. debug(F100,"nettchk SSL_ERROR_SSL","",0);
  5238. fflush(stderr);
  5239. fprintf(stderr,"nettchk() SSL_ERROR_SSL\n");
  5240. ERR_print_errors_fp(stderr);
  5241. }
  5242. #ifdef COMMENT
  5243. netclos();
  5244. rc = -1;
  5245. goto nettchk_return;
  5246. #else
  5247. x = -1;
  5248. break;
  5249. #endif
  5250. case SSL_ERROR_ZERO_RETURN:
  5251. debug(F100,"nettchk SSL_ERROR_ZERO_RETURN","",0);
  5252. netclos();
  5253. rc = -1;
  5254. goto nettchk_return;
  5255. default:
  5256. debug(F100,"nettchk SSL_ERROR_?????","",0);
  5257. netclos();
  5258. rc = -1;
  5259. goto nettchk_return;
  5260. }
  5261. #else /* OS2 */
  5262. /* Do not block */
  5263. x = -1;
  5264. #endif /* OS2 */
  5265. } else
  5266. #endif /* CK_SSL */
  5267. {
  5268. #ifdef OS2
  5269. x = socket_read(ttyfd,&ttibuf[ttibp+ttibn],
  5270. TTIBUFL-ttibp-ttibn); /* Returns -1 if no data */
  5271. #else /* OS2 */
  5272. x = socket_read(ttyfd,&c,1); /* Returns -1 if no data */
  5273. #endif /* OS2 */
  5274. }
  5275. s_errno = socket_errno; /* socket_errno may be a function */
  5276. debug(F101,"nettchk socket_read","",x);
  5277. #ifndef NON_BLOCK_IO
  5278. #ifdef OS2
  5279. #ifdef CK_SSL
  5280. RequestSSLMutex(SEM_INDEFINITE_WAIT);
  5281. #endif /* CK_SSL */
  5282. #endif /* OS2 */
  5283. y = 0; /* Turn off nonblocking reads */
  5284. z = socket_ioctl(ttyfd,FIONBIO,&y);
  5285. debug(F111,"nettchk FIONBIO","off",z);
  5286. #ifdef OS2
  5287. #ifdef CK_SSL
  5288. ReleaseSSLMutex();
  5289. #endif /* CK_SSL */
  5290. #endif /* OS2 */
  5291. #endif /* NON_BLOCK_IO */
  5292. #ifdef NT_TCP_OVERLAPPED
  5293. ionoblock = 0; /* For Overlapped I/O */
  5294. #endif /* NT_TCP_OVERLAPPED */
  5295. if (x == -1) {
  5296. debug(F101,"nettchk socket_read errno","",s_errno);
  5297. #ifdef OS2
  5298. if (os2socketerror(s_errno) < 0) {
  5299. rc = -1;
  5300. goto nettchk_return;
  5301. }
  5302. #endif /* OS2 */
  5303. } else if (x == 0) {
  5304. debug(F100,"nettchk connection closed","",0);
  5305. netclos(); /* *** *** */
  5306. rc = -1;
  5307. goto nettchk_return;
  5308. }
  5309. if (x >= 1) { /* Oops, actually got a byte? */
  5310. #ifdef OS2
  5311. /* In OS/2 we read directly into ttibuf[] */
  5312. ckhexdump("nettchk got real data",&ttibuf[ttibp+ttibn],x);
  5313. ttibn += x;
  5314. #else /* OS2 */
  5315. #ifdef CK_SSL
  5316. if ( ssl_active_flag || tls_active_flag ) {
  5317. ckhexdump("nettchk got real data",&ttibuf[ttibp+ttibn],x);
  5318. ttibn += x;
  5319. } else
  5320. #endif /* CK_SSL */
  5321. {
  5322. debug(F101,"nettchk socket_read char","",c);
  5323. debug(F101,"nettchk ttibp","",ttibp);
  5324. debug(F101,"nettchk ttibn","",ttibn);
  5325. /*
  5326. In the case of Overlapped I/O the character would have come from
  5327. the beginning of the buffer, so put it back.
  5328. */
  5329. if (ttibp > 0) {
  5330. ttibp--;
  5331. ttibuf[ttibp] = c;
  5332. ttibn++;
  5333. } else {
  5334. ttibuf[ttibp+ttibn] = c;
  5335. ttibn++;
  5336. }
  5337. }
  5338. #endif /* OS2 */
  5339. }
  5340. #else /* NOCOUNT */
  5341. if (ttnet == NET_TCPB) {
  5342. char dummy;
  5343. x = read(ttyfd,&dummy,0); /* Try to read nothing */
  5344. if (x < 0) { /* "Connection reset by peer" */
  5345. perror("TCP/IP"); /* or somesuch... */
  5346. ttclos(0); /* Close our end too. */
  5347. rc = -1;
  5348. goto nettchk_return;
  5349. }
  5350. }
  5351. #endif /* NOCOUNT */
  5352. }
  5353. #ifdef CK_KERBEROS
  5354. #ifdef KRB4
  5355. #ifdef RLOGCODE
  5356. if (ttnproto == NP_EK4LOGIN)
  5357. count += krb4_des_avail(ttyfd);
  5358. #endif /* RLOGCODE */
  5359. #endif /* KRB4 */
  5360. #ifdef KRB5
  5361. #ifdef RLOGCODE
  5362. if (ttnproto == NP_EK5LOGIN)
  5363. count += krb5_des_avail(ttyfd);
  5364. #endif /* RLOGCODE */
  5365. #ifdef KRB5_U2U
  5366. if (ttnproto == NP_K5U2U)
  5367. count += krb5_u2u_avail(ttyfd);
  5368. #endif /* KRB5_U2U */
  5369. #endif /* KRB5 */
  5370. #endif /* CK_KERBEROS */
  5371. debug(F101,"nettchk returns","",count+ttibn);
  5372. rc = count + ttibn;
  5373. nettchk_return:
  5374. #ifdef OS2
  5375. ReleaseTCPIPMutex();
  5376. #endif /* OS2 */
  5377. return(rc);
  5378. #else /* Not TCPIPLIB */
  5379. /*
  5380. UNIX just uses ttchk(), in which the ioctl() calls on the file descriptor
  5381. seem to work OK.
  5382. */
  5383. return(ttchk());
  5384. #endif /* TCPIPLIB */
  5385. /*
  5386. But what about X.25?
  5387. */
  5388. }
  5389. #ifndef OS2
  5390. VOID
  5391. nettout(i) int i; { /* Catch the alarm interrupts */
  5392. debug(F100,"nettout caught timeout","",0);
  5393. ttimoff();
  5394. cklongjmp(njbuf, -1);
  5395. }
  5396. #endif /* !OS2 */
  5397. #ifdef TCPIPLIB
  5398. VOID
  5399. #ifdef CK_ANSIC
  5400. donetinc(void * threadinfo)
  5401. #else /* CK_ANSIC */
  5402. donetinc(threadinfo) VOID * threadinfo;
  5403. #endif /* CK_ANSIC */
  5404. /* donetinc */ {
  5405. #ifdef NTSIG
  5406. extern int TlsIndex;
  5407. setint();
  5408. if (threadinfo) { /* Thread local storage... */
  5409. TlsSetValue(TlsIndex,threadinfo);
  5410. }
  5411. #endif /* NTSIG */
  5412. #ifdef CK_LOGIN
  5413. #ifdef NT
  5414. #ifdef IKSD
  5415. if (inserver)
  5416. setntcreds();
  5417. #endif /* IKSD */
  5418. #endif /* NT */
  5419. #endif /* CK_LOGIN */
  5420. while (1) {
  5421. if (ttbufr() < 0) /* Keep trying to refill it. */
  5422. break; /* Till we get an error. */
  5423. if (ttibn > 0) /* Or we get a character. */
  5424. break;
  5425. }
  5426. }
  5427. #endif /* TCPIPLIB */
  5428. VOID
  5429. #ifdef CK_ANSIC
  5430. failnetinc(void * threadinfo)
  5431. #else /* CK_ANSIC */
  5432. failnetinc(threadinfo) VOID * threadinfo;
  5433. #endif /* CK_ANSIC */
  5434. /* failnetinc */ {
  5435. ; /* Nothing to do on an error */
  5436. }
  5437. /* N E T X I N -- Input block of characters from network */
  5438. int
  5439. netxin(n,buf) int n; CHAR * buf; {
  5440. int len, i, j;
  5441. #ifdef TCPIPLIB
  5442. int rc;
  5443. #endif /* TCPIPLIB */
  5444. if (ttyfd == -1) {
  5445. debug(F100,"netxin socket is closed","",0);
  5446. return(-2);
  5447. }
  5448. #ifdef CK_KERBEROS
  5449. #ifdef KRB4
  5450. #ifdef RLOGCODE
  5451. if (ttnproto == NP_EK4LOGIN) {
  5452. if ((len = krb4_des_read(ttyfd,buf,n)) < 0)
  5453. return(-1);
  5454. else
  5455. return(len);
  5456. }
  5457. #endif /* RLOGCODE */
  5458. #endif /* KRB4 */
  5459. #ifdef KRB5
  5460. #ifdef RLOGCODE
  5461. if (ttnproto == NP_EK5LOGIN) {
  5462. if ((len = krb5_des_read(ttyfd,(char *)buf,n,0)) < 0)
  5463. return(-1);
  5464. else
  5465. return(len);
  5466. }
  5467. #endif /* RLOGCODE */
  5468. #ifdef KRB5_U2U
  5469. if (ttnproto == NP_K5U2U) {
  5470. if ((len = krb5_u2u_read(ttyfd,(char *)buf,n)) < 0)
  5471. return(-1);
  5472. else
  5473. return(len);
  5474. }
  5475. #endif /* KRB5_U2U */
  5476. #endif /* KRB5 */
  5477. #endif /* CK_KERBEROS */
  5478. #ifdef TCPIPLIB
  5479. #ifdef OS2
  5480. RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
  5481. #endif /* OS2 */
  5482. if (ttibn == 0)
  5483. if ((rc = ttbufr()) <= 0) {
  5484. #ifdef OS2
  5485. ReleaseTCPIPMutex();
  5486. #endif /* OS2 */
  5487. return(rc);
  5488. }
  5489. if (ttibn <= n) {
  5490. len = ttibn;
  5491. memcpy(buf,&ttibuf[ttibp],len); /* safe */
  5492. ttibp += len;
  5493. ttibn = 0;
  5494. } else {
  5495. memcpy(buf,&ttibuf[ttibp],n); /* safe */
  5496. ttibp += n;
  5497. ttibn -= n;
  5498. len = n;
  5499. }
  5500. #ifdef OS2
  5501. ReleaseTCPIPMutex();
  5502. #endif /* OS2 */
  5503. #else /* TCPIPLIB */
  5504. for (i = 0; i < n; i++) {
  5505. if ((j = netinc(0)) < 0) {
  5506. if (j < -1)
  5507. return(j);
  5508. else
  5509. break;
  5510. }
  5511. buf[i] = j;
  5512. }
  5513. len = i;
  5514. #endif /* TCPIPLIB */
  5515. #ifdef COMMENT
  5516. #ifdef CK_ENCRYPTION
  5517. /* This would be great if it worked. But what if the buffer we read */
  5518. /* contains a telnet negotiation that changes the state of the */
  5519. /* encryption. If so, we would be either decrypting unencrypted text */
  5520. /* or not decrypting encrypted text. So we must move this call to */
  5521. /* all functions that call ttxin(). In OS2 that means os2_netxin() */
  5522. /* where the Telnet Negotiations are handled. */
  5523. if (u_encrypt)
  5524. ck_tn_decrypt(buf,len);
  5525. #endif /* CK_ENCRYPTION */
  5526. #endif /* COMMENT */
  5527. return(len);
  5528. }
  5529. /* N E T I N C -- Input character from network */
  5530. #ifdef NETLEBUF
  5531. #define LEBUF
  5532. #endif /* NETLEBUF */
  5533. #ifdef TTLEBUF
  5534. #define LEBUF
  5535. #endif /* TTLEBUF */
  5536. #ifndef LEBUF
  5537. #ifdef OS2
  5538. #define LEBUF
  5539. #endif /* OS2 */
  5540. #endif /* LEBUF */
  5541. int
  5542. netinc(timo) int timo; {
  5543. #ifdef TCPIPLIB
  5544. int x; unsigned char c; /* The locals. */
  5545. #ifdef NETLEBUF
  5546. if (ttpush >= 0) {
  5547. debug(F111,"netinc","ttpush",ttpush);
  5548. c = ttpush;
  5549. ttpush = -1;
  5550. return(c);
  5551. }
  5552. if (le_data) {
  5553. if (le_getchar((CHAR *)&c) > 0) {
  5554. debug(F111,"netinc le_getchar","c",c);
  5555. return(c);
  5556. }
  5557. }
  5558. #endif /* NETLEBUF */
  5559. if (ttyfd == -1) {
  5560. debug(F100,"netinc socket is closed","",0);
  5561. return(-2);
  5562. }
  5563. #ifdef CK_KERBEROS
  5564. #ifdef KRB4
  5565. #ifdef RLOGCODE
  5566. if (ttnproto == NP_EK4LOGIN) {
  5567. if ((x = krb4_des_read(ttyfd,&c,1)) == 0)
  5568. return(-1);
  5569. else if (x < 0)
  5570. return(-2);
  5571. else
  5572. return(c);
  5573. }
  5574. #endif /* RLOGCODE */
  5575. #endif /* KRB4 */
  5576. #ifdef KRB5
  5577. #ifdef RLOGCODE
  5578. if (ttnproto == NP_EK5LOGIN) {
  5579. if ((x = krb5_des_read(ttyfd,&c,1,0)) == 0)
  5580. return(-1);
  5581. else if (x < 0)
  5582. return(-2);
  5583. else
  5584. return(c);
  5585. }
  5586. #endif /* RLOGCODE */
  5587. #ifdef KRB5_U2U
  5588. if (ttnproto == NP_K5U2U) {
  5589. if ((x = krb5_u2u_read(ttyfd,&c,1)) == 0)
  5590. return(-1);
  5591. else if (x < 0)
  5592. return(-2);
  5593. else
  5594. return(c);
  5595. }
  5596. #endif /* KRB5_U2U */
  5597. #endif /* KRB5 */
  5598. #endif /* CK_KERBEROS */
  5599. #ifdef OS2
  5600. RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
  5601. #endif /* OS2 */
  5602. if (ttibn > 0) { /* Something in internal buffer? */
  5603. #ifdef COMMENT
  5604. debug(F100,"netinc char in buf","",0); /* Yes. */
  5605. #endif /* COMMENT */
  5606. x = 0; /* Success. */
  5607. } else { /* Else must read from network. */
  5608. x = -1; /* Assume failure. */
  5609. #ifdef DEBUG
  5610. debug(F101,"netinc goes to net, timo","",timo);
  5611. #endif /* DEBUG */
  5612. #ifdef CK_SSL
  5613. /*
  5614. * In the case of OpenSSL, it is possible that there is still
  5615. * data waiting in the SSL session buffers that has not yet
  5616. * been read by Kermit. If this is the case we must process
  5617. * it without calling select() because select() will not return
  5618. * with an indication that there is data to be read from the
  5619. * socket. If there is no data pending in the SSL session
  5620. * buffers then fall through to the select() code and wait for
  5621. * some data to arrive.
  5622. */
  5623. if (ssl_active_flag) {
  5624. x = SSL_pending(ssl_con);
  5625. if (x < 0) {
  5626. debug(F111,"netinc","SSL_pending error",x);
  5627. netclos();
  5628. #ifdef OS2
  5629. ReleaseTCPIPMutex();
  5630. #endif /* OS2 */
  5631. return(-1);
  5632. } else if ( x > 0 ) {
  5633. if ( ttbufr() >= 0 ) {
  5634. x = netinc(timo);
  5635. #ifdef OS2
  5636. ReleaseTCPIPMutex();
  5637. #endif /* OS2 */
  5638. return(x);
  5639. }
  5640. }
  5641. x = -1;
  5642. } else if (tls_active_flag) {
  5643. x = SSL_pending(tls_con);
  5644. if (x < 0) {
  5645. debug(F111,"netinc","TLS_pending error",x);
  5646. netclos();
  5647. #ifdef OS2
  5648. ReleaseTCPIPMutex();
  5649. #endif /* OS2 */
  5650. return(-1);
  5651. } else if ( x > 0 ) {
  5652. if ( ttbufr() >= 0 ) {
  5653. x = netinc(timo);
  5654. #ifdef OS2
  5655. ReleaseTCPIPMutex();
  5656. #endif /* OS2 */
  5657. return(x);
  5658. }
  5659. }
  5660. x = -1;
  5661. }
  5662. #endif /* CK_SSL */
  5663. #ifndef LEBUF
  5664. if (timo == 0) { /* Untimed case. */
  5665. while (1) { /* Wait forever if necessary. */
  5666. if (ttbufr() < 0) /* Refill buffer. */
  5667. break; /* Error, fail. */
  5668. if (ttibn > 0) { /* Success. */
  5669. x = 0;
  5670. break;
  5671. }
  5672. }
  5673. } else /* Timed case... */
  5674. #endif /* LEBUF */
  5675. {
  5676. #ifdef NT_TCP_OVERLAPPED
  5677. /* This code is for use on NT when we are using */
  5678. /* Overlapped I/O to handle reads. In the case */
  5679. /* of outstanding reads select() doesn't work */
  5680. if (WaitForOverlappedReadData(timo)) {
  5681. while (1) {
  5682. if (ttbufr() < 0) /* Keep trying to refill it. */
  5683. break; /* Till we get an error. */
  5684. if (ttibn > 0) { /* Or we get a character. */
  5685. x = 0;
  5686. break;
  5687. }
  5688. }
  5689. }
  5690. #else /* NT_TCP_OVERLAPPED */
  5691. #ifdef BSDSELECT
  5692. fd_set rfds;
  5693. struct timeval tv;
  5694. int timeout = timo < 0 ? -timo : 1000 * timo;
  5695. debug(F101,"netinc BSDSELECT","",timo);
  5696. for ( ; timeout >= 0; timeout -= (timo ? 100 : 0)) {
  5697. int rc;
  5698. debug(F111,"netinc","timeout",timeout);
  5699. /* Don't move select() initialization out of the loop. */
  5700. FD_ZERO(&rfds);
  5701. FD_SET(ttyfd, &rfds);
  5702. tv.tv_sec = tv.tv_usec = 0L;
  5703. if (timo)
  5704. tv.tv_usec = (long) 100000L;
  5705. else
  5706. tv.tv_sec = 30;
  5707. #ifdef NT
  5708. WSASafeToCancel = 1;
  5709. #endif /* NT */
  5710. rc = select(FD_SETSIZE,
  5711. #ifdef __DECC
  5712. #ifdef INTSELECT
  5713. (int *)
  5714. #else /* def INTSELECT */
  5715. (fd_set *)
  5716. #endif /* def INTSELECT [else] */
  5717. #else /* def __DECC */
  5718. (fd_set *)
  5719. #endif /* def __DECC [else] */
  5720. &rfds, NULL, NULL, &tv);
  5721. if (rc < 0) {
  5722. int s_errno = socket_errno;
  5723. debug(F111,"netinc","select",rc);
  5724. debug(F111,"netinc","socket_errno",s_errno);
  5725. if (s_errno) {
  5726. #ifdef OS2
  5727. ReleaseTCPIPMutex();
  5728. #endif /* OS2 */
  5729. return(-1);
  5730. }
  5731. }
  5732. debug(F111,"netinc","select",rc);
  5733. #ifdef NT
  5734. WSASafeToCancel = 0;
  5735. #endif /* NT */
  5736. if (!FD_ISSET(ttyfd, &rfds)) {
  5737. #ifdef LEBUF
  5738. if (le_inbuf() > 0) {
  5739. timeout = -1;
  5740. break;
  5741. }
  5742. #endif /* LEBUF */
  5743. /* If waiting forever we have no way of knowing if the */
  5744. /* socket closed so try writing a 0-length TCP packet */
  5745. /* which should force an error if the socket is closed */
  5746. if (!timo) {
  5747. if ((rc = socket_write(ttyfd,"",0)) < 0) {
  5748. int s_errno = socket_errno;
  5749. debug(F101,"netinc socket_write error","",s_errno);
  5750. #ifdef OS2
  5751. if (os2socketerror(s_errno) < 0) {
  5752. ReleaseTCPIPMutex();
  5753. return(-2);
  5754. }
  5755. ReleaseTCPIPMutex();
  5756. #endif /* OS2 */
  5757. return(-1); /* Call it an i/o error */
  5758. }
  5759. }
  5760. continue;
  5761. }
  5762. while (1) {
  5763. if (ttbufr() < 0) { /* Keep trying to refill it. */
  5764. timeout = -1;
  5765. break; /* Till we get an error. */
  5766. }
  5767. if (ttibn > 0) { /* Or we get a character. */
  5768. x = 0;
  5769. timeout = -1;
  5770. break;
  5771. }
  5772. }
  5773. }
  5774. #ifdef NT
  5775. WSASafeToCancel = 0;
  5776. #endif /* NT */
  5777. #else /* !BSDSELECT */
  5778. #ifdef IBMSELECT
  5779. /*
  5780. Was used by OS/2, currently not used, but might come in handy some day...
  5781. ... and it came in handy! For our TCP/IP layer, it avoids all the fd_set
  5782. and timeval stuff since this is the only place where it is used.
  5783. */
  5784. int socket = ttyfd;
  5785. int timeout = timo < 0 ? -timo : 1000 * timo;
  5786. debug(F101,"netinc IBMSELECT","",timo);
  5787. for ( ; timeout >= 0; timeout -= (timo ? 100 : 0)) {
  5788. if (select(&socket, 1, 0, 0, 100L) == 1) {
  5789. while (1) {
  5790. if (ttbufr() < 0) { /* Keep trying to refill it. */
  5791. timeout = -1;
  5792. break; /* Till we get an error. */
  5793. }
  5794. if (ttibn > 0) { /* Or we get a character. */
  5795. x = 0;
  5796. timeout = -1;
  5797. break;
  5798. }
  5799. }
  5800. }
  5801. #ifdef LEBUF
  5802. else if (le_inbuf() > 0) {
  5803. timeout = -1;
  5804. break;
  5805. }
  5806. #endif /* LEBUF */
  5807. }
  5808. #else /* !IBMSELECT */
  5809. #ifdef WINSOCK
  5810. /* Actually, under WinSock we have a better mechanism than select() */
  5811. /* for setting timeouts (SO_RCVTIMEO, SO_SNDTIMEO) */
  5812. SOCKET socket = ttyfd;
  5813. debug(F101,"netinc NTSELECT","",timo);
  5814. if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timo,
  5815. sizeof(timo)) == NO_ERROR)
  5816. while (1) {
  5817. if (ttbufr() < 0) /* Keep trying to refill it. */
  5818. break; /* Till we get an error. */
  5819. if (ttibn > 0) { /* Or we get a character. */
  5820. x = 0;
  5821. break;
  5822. }
  5823. }
  5824. #else /* WINSOCK */
  5825. /*
  5826. If we can't use select(), then we use the regular alarm()/signal()
  5827. timeout mechanism.
  5828. */
  5829. debug(F101,"netinc alarm","",timo);
  5830. x = alrm_execute(ckjaddr(njbuf),timo,nettout,donetinc,failnetinc);
  5831. ttimoff(); /* Timer off. */
  5832. #endif /* WINSOCK */
  5833. #endif /* IBMSELECT */
  5834. #endif /* BSDSELECT */
  5835. #endif /* NT_TCP_OVERLAPPED */
  5836. }
  5837. }
  5838. #ifdef LEBUF
  5839. if (le_inbuf() > 0) { /* If data was inserted into the */
  5840. if (le_getchar((CHAR *)&c) > 0) {/* Local Echo buffer while the */
  5841. #ifdef OS2 /* was taking place do not mix */
  5842. ReleaseTCPIPMutex(); /* the le data with the net data */
  5843. #endif /* OS2 */
  5844. return(c);
  5845. }
  5846. }
  5847. #endif /* LEBUF */
  5848. if (x < 0) { /* Return -1 if we failed. */
  5849. debug(F100,"netinc timed out","",0);
  5850. #ifdef OS2
  5851. ReleaseTCPIPMutex();
  5852. #endif /* OS2 */
  5853. return(-1);
  5854. } else { /* Otherwise */
  5855. c = ttibuf[ttibp]; /* Return the first char in ttibuf[] */
  5856. if (deblog) {
  5857. #ifndef COMMENT
  5858. debug(F101,"netinc returning","",c);
  5859. #endif /* COMMENT */
  5860. if (c == 0) {
  5861. debug(F101,"netinc 0 ttibn","",ttibn);
  5862. debug(F101,"netinc 0 ttibp","",ttibp);
  5863. #ifdef BETADEBUG
  5864. {
  5865. #ifdef OS2
  5866. extern int tt_type_mode;
  5867. if ( !ISVTNT(tt_type_mode) )
  5868. #endif /* OS2 */
  5869. ckhexdump("netinc &ttbuf[ttibp]",&ttibuf[ttibp],ttibn);
  5870. }
  5871. #endif /* BETADEBUG */
  5872. }
  5873. }
  5874. ttibp++;
  5875. ttibn--;
  5876. #ifdef OS2
  5877. ReleaseTCPIPMutex();
  5878. #endif /* OS2 */
  5879. #ifdef CK_ENCRYPTION
  5880. if (TELOPT_U(TELOPT_ENCRYPTION))
  5881. ck_tn_decrypt(&c,1);
  5882. #endif /* CK_ENCRYPTION */
  5883. return(c);
  5884. }
  5885. #else /* Not using TCPIPLIB */
  5886. return(-1);
  5887. #endif /* TCPIPLIB */
  5888. }
  5889. /* N E T T O L -- Output a string of bytes to the network */
  5890. /*
  5891. Call with s = pointer to string, n = length.
  5892. Returns number of bytes actually written on success, or
  5893. -1 on i/o error, -2 if called improperly.
  5894. */
  5895. int
  5896. nettol(s,n) CHAR *s; int n; {
  5897. #ifdef TCPIPLIB
  5898. int count = 0;
  5899. int len = n;
  5900. int try = 0;
  5901. if (ttyfd == -1) {
  5902. debug(F100,"nettol socket is closed","",0);
  5903. return -1;
  5904. }
  5905. debug(F101,"nettol TCPIPLIB ttnet","",ttnet);
  5906. #ifdef COMMENT
  5907. ckhexdump("nettol",s,n);
  5908. #endif /* COMMENT */
  5909. #ifdef CK_KERBEROS
  5910. #ifdef KRB4
  5911. #ifdef RLOGCODE
  5912. if (ttnproto == NP_EK4LOGIN) {
  5913. return(krb4_des_write(ttyfd,s,n));
  5914. }
  5915. #endif /* RLOGCODE */
  5916. #endif /* KRB4 */
  5917. #ifdef KRB5
  5918. #ifdef RLOGCODE
  5919. if (ttnproto == NP_EK5LOGIN) {
  5920. return(krb5_des_write(ttyfd,s,n,0));
  5921. }
  5922. #endif /* RLOGCODE */
  5923. #ifdef KRB5_U2U
  5924. if (ttnproto == NP_K5U2U) {
  5925. return(krb5_u2u_write(ttyfd,s,n));
  5926. }
  5927. #endif /* KRB5_U2U */
  5928. #endif /* KRB5 */
  5929. #endif /* CK_KERBEROS */
  5930. #ifdef CK_ENCRYPTION
  5931. if (TELOPT_ME(TELOPT_ENCRYPTION))
  5932. ck_tn_encrypt(s,n);
  5933. #endif /* CK_ENCRYPTION */
  5934. #ifdef CK_SSL
  5935. if (ssl_active_flag || tls_active_flag) {
  5936. int error, r;
  5937. /* Write using SSL */
  5938. ssl_retry:
  5939. if (ssl_active_flag)
  5940. r = SSL_write(ssl_con, s, len /* >1024?1024:len */);
  5941. else
  5942. r = SSL_write(tls_con, s, len /* >1024?1024:len */);
  5943. switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,r)) {
  5944. case SSL_ERROR_NONE:
  5945. debug(F111,"nettol","SSL_write",r);
  5946. if ( r == len )
  5947. return(n);
  5948. s += r;
  5949. len -= r;
  5950. goto ssl_retry;
  5951. case SSL_ERROR_WANT_WRITE:
  5952. debug(F100,"nettol SSL_ERROR_WANT_WRITE","",0);
  5953. return(-1);
  5954. case SSL_ERROR_WANT_READ:
  5955. debug(F100,"nettol SSL_ERROR_WANT_READ","",0);
  5956. return(-1);
  5957. case SSL_ERROR_SYSCALL:
  5958. if ( r == 0 ) { /* EOF */
  5959. netclos();
  5960. return(-2);
  5961. } else {
  5962. int rc = -1;
  5963. #ifdef NT
  5964. int gle = GetLastError();
  5965. debug(F111,"nettol SSL_ERROR_SYSCALL",
  5966. "GetLastError()",gle);
  5967. rc = os2socketerror(gle);
  5968. if (rc == -1)
  5969. rc = -2;
  5970. else if ( rc == -2 )
  5971. rc = -1;
  5972. #endif /* NT */
  5973. return(rc);
  5974. }
  5975. case SSL_ERROR_WANT_X509_LOOKUP:
  5976. debug(F100,"nettol SSL_ERROR_WANT_X509_LOOKUP","",0);
  5977. netclos();
  5978. return(-2);
  5979. case SSL_ERROR_SSL:
  5980. debug(F100,"nettol SSL_ERROR_SSL","",0);
  5981. if (bio_err!=NULL) {
  5982. int len;
  5983. extern char ssl_err[];
  5984. BIO_printf(bio_err,"nettol() SSL_ERROR_SSL\n");
  5985. ERR_print_errors(bio_err);
  5986. len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
  5987. ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
  5988. debug(F110,"nettol SSL_ERROR_SSL",ssl_err,0);
  5989. if (ssl_debug_flag)
  5990. printf(ssl_err);
  5991. } else if (ssl_debug_flag) {
  5992. debug(F100,"nettol SSL_ERROR_SSL","",0);
  5993. fflush(stderr);
  5994. fprintf(stderr,"nettol() SSL_ERROR_SSL\n");
  5995. ERR_print_errors_fp(stderr);
  5996. }
  5997. #ifdef COMMENT
  5998. netclos();
  5999. return(-2);
  6000. #else
  6001. return(-1);
  6002. #endif
  6003. case SSL_ERROR_ZERO_RETURN:
  6004. debug(F100,"nettol SSL_ERROR_ZERO_RETURN","",0);
  6005. netclos();
  6006. return(-2);
  6007. default:
  6008. debug(F100,"nettol SSL_ERROR_?????","",0);
  6009. netclos();
  6010. return(-2);
  6011. }
  6012. }
  6013. #endif /* CK_SSL */
  6014. nettol_retry:
  6015. try++; /* Increase the try counter */
  6016. if (ttnet == NET_TCPB) {
  6017. #ifdef BSDSELECT
  6018. fd_set wfds;
  6019. struct timeval tv;
  6020. debug(F101,"nettol BSDSELECT","",0);
  6021. tv.tv_usec = 0L;
  6022. tv.tv_sec=30;
  6023. #ifdef NT
  6024. WSASafeToCancel = 1;
  6025. #endif /* NT */
  6026. #ifdef STREAMING
  6027. do_select:
  6028. #endif /* STREAMING */
  6029. FD_ZERO(&wfds);
  6030. FD_SET(ttyfd, &wfds);
  6031. if (select(FD_SETSIZE, NULL,
  6032. #ifdef __DECC
  6033. #ifndef __DECC_VER
  6034. (int *)
  6035. #endif /* __DECC_VER */
  6036. #endif /* __DECC */
  6037. &wfds, NULL, &tv) < 0) {
  6038. int s_errno = socket_errno;
  6039. debug(F101,"nettol select failed","",s_errno);
  6040. #ifdef BETADEBUG
  6041. printf("nettol select failed: %d\n", s_errno);
  6042. #endif /* BETADEBUG */
  6043. #ifdef NT
  6044. WSASafeToCancel = 0;
  6045. if (!win95selectbug)
  6046. #endif /* NT */
  6047. return(-1);
  6048. }
  6049. if (!FD_ISSET(ttyfd, &wfds)) {
  6050. #ifdef STREAMING
  6051. if (streaming)
  6052. goto do_select;
  6053. #endif /* STREAMING */
  6054. debug(F111,"nettol","!FD_ISSET",ttyfd);
  6055. #ifdef NT
  6056. WSASafeToCancel = 0;
  6057. if (!win95selectbug)
  6058. #endif /* NT */
  6059. return(-1);
  6060. }
  6061. #ifdef NT
  6062. WSASafeToCancel = 0;
  6063. #endif /* NT */
  6064. #else /* BSDSELECT */
  6065. #ifdef IBMSELECT
  6066. {
  6067. int tries = 0;
  6068. debug(F101,"nettol IBMSELECT","",0);
  6069. while (select(&ttyfd, 0, 1, 0, 1000) != 1) {
  6070. int count;
  6071. if (tries++ >= 60) {
  6072. /* if after 60 seconds we can't get permission to write */
  6073. debug(F101,"nettol select failed","",socket_errno);
  6074. return(-1);
  6075. }
  6076. if ((count = nettchk()) < 0) {
  6077. debug(F111,"nettol","nettchk()",count);
  6078. return(count);
  6079. }
  6080. }
  6081. }
  6082. #endif /* IBMSELECT */
  6083. #endif /* BSDSELECT */
  6084. if ((count = socket_write(ttyfd,s,n)) < 0) {
  6085. int s_errno = socket_errno; /* maybe a function */
  6086. debug(F101,"nettol socket_write error","",s_errno);
  6087. #ifdef OS2
  6088. if (os2socketerror(s_errno) < 0)
  6089. return(-2);
  6090. #endif /* OS2 */
  6091. return(-1); /* Call it an i/o error */
  6092. }
  6093. if (count < n) {
  6094. debug(F111,"nettol socket_write",s,count);
  6095. if (try > 25) {
  6096. /* don't try more than 25 times */
  6097. debug(F100,"nettol tried more than 25 times","",0);
  6098. return(-1);
  6099. }
  6100. if (count > 0) {
  6101. s += count;
  6102. n -= count;
  6103. }
  6104. debug(F111,"nettol retry",s,n);
  6105. goto nettol_retry;
  6106. } else {
  6107. debug(F111,"nettol socket_write",s,count);
  6108. return(len); /* success - return total length */
  6109. }
  6110. } else
  6111. return(-2);
  6112. #else
  6113. debug(F100,"nettol TCPIPLIB not defined","",0);
  6114. return(-2);
  6115. #endif /* TCPIPLIB */
  6116. }
  6117. /* N E T T O C -- Output character to network */
  6118. /*
  6119. Call with character to be transmitted.
  6120. Returns 0 if transmission was successful, or
  6121. -1 upon i/o error, or -2 if called improperly.
  6122. */
  6123. int
  6124. #ifdef CK_ANSIC
  6125. nettoc(CHAR c)
  6126. #else
  6127. nettoc(c) CHAR c;
  6128. #endif /* CK_ANSIC */
  6129. /* nettoc */ {
  6130. #ifdef UNIX
  6131. return(ttoc(c));
  6132. #else
  6133. #ifdef TCPIPLIB
  6134. unsigned char cc;
  6135. if (ttyfd == -1) {
  6136. debug(F100,"nettoc socket is closed","",0);
  6137. return -1;
  6138. }
  6139. cc = c;
  6140. debug(F101,"nettoc cc","",cc);
  6141. #ifdef CK_KERBEROS
  6142. #ifdef KRB4
  6143. #ifdef RLOGCODE
  6144. if (ttnproto == NP_EK4LOGIN) {
  6145. return(krb4_des_write(ttyfd,&cc,1)==1?0:-1);
  6146. }
  6147. #endif /* RLOGCODE */
  6148. #endif /* KRB4 */
  6149. #ifdef KRB5
  6150. #ifdef RLOGCODE
  6151. if (ttnproto == NP_EK5LOGIN) {
  6152. return(krb5_des_write(ttyfd,&cc,1,0)==1?0:-1);
  6153. }
  6154. #endif /* RLOGCODE */
  6155. #ifdef KRB5_U2U
  6156. if (ttnproto == NP_K5U2U) {
  6157. return(krb5_u2u_write(ttyfd,&cc,1)==1?0:-1);
  6158. }
  6159. #endif /* KRB5_U2U */
  6160. #endif /* KRB5 */
  6161. #endif /* CK_KERBEROS */
  6162. #ifdef CK_ENCRYPTION
  6163. if ( TELOPT_ME(TELOPT_ENCRYPTION) )
  6164. ck_tn_encrypt(&cc,1);
  6165. #endif /* CK_ENCRYPTION */
  6166. #ifdef CK_SSL
  6167. if (ssl_active_flag || tls_active_flag) {
  6168. int len, error;
  6169. /* Write using SSL */
  6170. ssl_retry:
  6171. if (ssl_active_flag)
  6172. len = SSL_write(ssl_con, &cc, 1);
  6173. else
  6174. len = SSL_write(tls_con, &cc, 1);
  6175. switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,len)) {
  6176. case SSL_ERROR_NONE:
  6177. debug(F111,"nettoc","SSL_write",len);
  6178. return(len == 1 ? 0 : -1);
  6179. case SSL_ERROR_WANT_WRITE:
  6180. case SSL_ERROR_WANT_READ:
  6181. return(-1);
  6182. case SSL_ERROR_SYSCALL:
  6183. if ( len == 0 ) { /* EOF */
  6184. netclos();
  6185. return(-2);
  6186. } else {
  6187. int rc = -1;
  6188. #ifdef NT
  6189. int gle = GetLastError();
  6190. debug(F111,"nettoc SSL_ERROR_SYSCALL",
  6191. "GetLastError()",gle);
  6192. rc = os2socketerror(gle);
  6193. if (rc == -1)
  6194. rc = -2;
  6195. else if ( rc == -2 )
  6196. rc = -1;
  6197. #endif /* NT */
  6198. return(rc);
  6199. }
  6200. case SSL_ERROR_SSL:
  6201. if (bio_err!=NULL) {
  6202. int len;
  6203. extern char ssl_err[];
  6204. BIO_printf(bio_err,"nettoc() SSL_ERROR_SSL\n");
  6205. ERR_print_errors(bio_err);
  6206. len = BIO_read(bio_err,ssl_err,SSL_ERR_BFSZ);
  6207. ssl_err[len < SSL_ERR_BFSZ ? len : SSL_ERR_BFSZ] = '\0';
  6208. debug(F110,"nettoc SSL_ERROR_SSL",ssl_err,0);
  6209. if (ssl_debug_flag)
  6210. printf(ssl_err);
  6211. } else if (ssl_debug_flag) {
  6212. debug(F100,"nettoc SSL_ERROR_SSL","",0);
  6213. fflush(stderr);
  6214. fprintf(stderr,"nettoc() SSL_ERROR_SSL\n");
  6215. ERR_print_errors_fp(stderr);
  6216. }
  6217. return(-1);
  6218. break;
  6219. case SSL_ERROR_WANT_X509_LOOKUP:
  6220. case SSL_ERROR_ZERO_RETURN:
  6221. default:
  6222. netclos();
  6223. return(-2);
  6224. }
  6225. }
  6226. #endif /* CK_SSL */
  6227. if (ttnet == NET_TCPB) {
  6228. #ifdef BSDSELECT
  6229. fd_set wfds;
  6230. struct timeval tv;
  6231. debug(F101,"nettoc BSDSELECT","",0);
  6232. tv.tv_usec = 0L;
  6233. tv.tv_sec = 30;
  6234. #ifdef STREAMING
  6235. do_select:
  6236. #endif /* STREAMING */
  6237. FD_ZERO(&wfds);
  6238. FD_SET(ttyfd, &wfds);
  6239. if (select(FD_SETSIZE, NULL,
  6240. #ifdef __DECC
  6241. #ifndef __DECC_VER
  6242. (int *)
  6243. #endif /* __DECC_VER */
  6244. #endif /* __DECC */
  6245. &wfds, NULL, &tv) < 0) {
  6246. int s_errno = socket_errno;
  6247. debug(F101,"nettoc select failed","",s_errno);
  6248. #ifdef BETADEBUG
  6249. printf("nettoc select failed: %d\n", s_errno);
  6250. #endif /* BETADEBUG */
  6251. #ifdef NT
  6252. WSASafeToCancel = 0;
  6253. if (!win95selectbug)
  6254. #endif /* NT */
  6255. return(-1);
  6256. }
  6257. if (!FD_ISSET(ttyfd, &wfds)) {
  6258. #ifdef STREAMING
  6259. if (streaming)
  6260. goto do_select;
  6261. #endif /* STREAMING */
  6262. debug(F111,"nettoc","!FD_ISSET",ttyfd);
  6263. #ifdef NT
  6264. WSASafeToCancel = 0;
  6265. if (!win95selectbug)
  6266. #endif /* NT */
  6267. return(-1);
  6268. }
  6269. #ifdef NT
  6270. WSASafeToCancel = 0;
  6271. #endif /* NT */
  6272. #else /* BSDSELECT */
  6273. #ifdef IBMSELECT
  6274. {
  6275. int tries = 0;
  6276. while (select(&ttyfd, 0, 1, 0, 1000) != 1) {
  6277. int count;
  6278. if (tries++ >= 60) {
  6279. /* if after 60 seconds we can't get permission to write */
  6280. debug(F101,"nettoc select failed","",socket_errno);
  6281. return(-1);
  6282. }
  6283. if ((count = nettchk()) < 0) {
  6284. debug(F111,"nettoc","nettchk()",count);
  6285. return(count);
  6286. }
  6287. }
  6288. }
  6289. #endif /* IBMSELECT */
  6290. #endif /* BSDSELECT */
  6291. if (socket_write(ttyfd,&cc,1) < 1) {
  6292. int s_errno = socket_errno; /* maybe a function */
  6293. debug(F101,"nettoc socket_write error","",s_errno);
  6294. #ifdef OS2
  6295. if (os2socketerror(s_errno) < 0)
  6296. return(-2);
  6297. #endif /* OS2 */
  6298. return(-1);
  6299. }
  6300. debug(F101,"nettoc socket_write","", cc);
  6301. return(0);
  6302. } else return(-2);
  6303. #else
  6304. return(-2);
  6305. #endif /* TCPIPLIB */
  6306. #endif /* UNIX */
  6307. }
  6308. /* N E T F L U I -- Flush network input buffer */
  6309. #ifdef TNCODE
  6310. static int
  6311. #ifdef CK_ANSIC
  6312. netgetc(int timo) /* Input function to point to... */
  6313. #else /* CK_ANSIC */
  6314. netgetc(timo) int timo;
  6315. #endif /* CK_ANSIC */
  6316. { /* ...in the tn_doop() call */
  6317. #ifdef TCPIPLIB
  6318. return netinc(timo);
  6319. #else /* TCPIPLIB */
  6320. return ttinc(timo);
  6321. #endif /* TCPIPLIB */
  6322. }
  6323. #endif /* TNCODE */
  6324. int
  6325. netflui() {
  6326. int n;
  6327. int ch;
  6328. #ifdef NETLEBUF
  6329. ttpush = -1; /* Clear the peek-ahead char */
  6330. while (le_data && (le_inbuf() > 0)) {
  6331. CHAR ch = '\0';
  6332. if (le_getchar(&ch) > 0) {
  6333. debug(F101,"ttflui le_inbuf ch","",ch);
  6334. }
  6335. }
  6336. #endif /* NETLEBUF */
  6337. #ifdef TCPIPLIB
  6338. #ifdef OS2
  6339. RequestTCPIPMutex(SEM_INDEFINITE_WAIT);
  6340. #endif /* OS2 */
  6341. #ifdef TNCODE
  6342. if (ttnproto == NP_TELNET) {
  6343. /* Netflui must process Telnet negotiations or get out of sync */
  6344. if ((n = nettchk()) <= 0)
  6345. goto exit_flui;
  6346. while (n-- > 0) {
  6347. ch = netinc(1);
  6348. if (ch == IAC) {
  6349. extern int duplex; /* this really shouldn't be here but ... */
  6350. int tx = tn_doop((CHAR)(ch & 0xff),duplex,netgetc);
  6351. if (tx == 1) duplex = 1;
  6352. else if (tx == 2) duplex = 0;
  6353. n = nettchk();
  6354. }
  6355. }
  6356. } else
  6357. #endif /* TNCODE */
  6358. {
  6359. ttibuf[ttibp+ttibn] = '\0';
  6360. debug(F111,"netflui 1",ttibuf,ttibn);
  6361. #ifdef CK_ENCRYPTION
  6362. if (TELOPT_U(TELOPT_ENCRYPTION)) {
  6363. ck_tn_decrypt(&ttibuf[ttibp],ttibn);
  6364. }
  6365. #endif /* CK_ENCRYPTION */
  6366. ttibn = ttibp = 0; /* Flush internal buffer *FIRST* */
  6367. if (ttyfd < 1)
  6368. goto exit_flui;
  6369. if ((n = nettchk()) > 0) { /* Now see what's waiting on the net */
  6370. if (n > TTIBUFL) n = TTIBUFL; /* and sponge it up */
  6371. debug(F101,"netflui 2","",n); /* ... */
  6372. n = socket_read(ttyfd,ttibuf,n); /* into our buffer */
  6373. if (n >= 0) ttibuf[n] = '\0';
  6374. debug(F111,"netflui 3",ttibuf,n);
  6375. #ifdef CK_ENCRYPTION
  6376. if (TELOPT_U(TELOPT_ENCRYPTION)) {
  6377. ck_tn_decrypt(&ttibuf[ttibp],n);
  6378. }
  6379. #endif /* CK_ENCRYPTION */
  6380. ttibuf[0] = '\0';
  6381. }
  6382. }
  6383. #else /* !TCPIPLIB */
  6384. if (ttyfd < 1)
  6385. goto exit_flui;
  6386. #ifdef TNCODE
  6387. if (ttnproto == NP_TELNET) {
  6388. if ((n = ttchk()) <= 0)
  6389. goto exit_flui;
  6390. while (n-- >= 0) {
  6391. /* Netflui must process Telnet negotiations or get out of sync */
  6392. ch = ttinc(1);
  6393. if (ch == IAC) {
  6394. extern int duplex; /* this really shouldn't be here but ... */
  6395. int tx = tn_doop((CHAR)(ch & 0xff),duplex,netgetc);
  6396. if (tx == 1) duplex = 1;
  6397. else if (tx == 2) duplex = 0;
  6398. n = ttchk();
  6399. }
  6400. };
  6401. } else
  6402. #endif /* TNCODE */
  6403. if ((n = ttchk()) > 0) {
  6404. debug(F101,"netflui non-TCPIPLIB","",n);
  6405. while ((n--) && ttinc(1) > -1) /* Don't worry, ttinc() is buffered */
  6406. ; /* and it handles the decryption... */
  6407. }
  6408. #endif /* TCPIPLIB */
  6409. exit_flui:
  6410. #ifdef OS2
  6411. ReleaseTCPIPMutex();
  6412. #endif /* OS2 */
  6413. return(0);
  6414. }
  6415. #ifdef CK_KERBEROS
  6416. /* The following two functions are required for encrypted rlogin */
  6417. /* They are called with nettoc() or nettol() are transmitting */
  6418. /* encrypted data. They call a function to encrypt the data */
  6419. /* and that function needs to be able to write to/read from the */
  6420. /* network in an unimpeded manner. Hence, these two simple fns. */
  6421. int
  6422. net_write(fd, buf, len)
  6423. int fd;
  6424. register const char *buf;
  6425. int len;
  6426. {
  6427. int cc;
  6428. register int wrlen = len;
  6429. do {
  6430. #ifdef TCPIPLIB
  6431. cc = socket_write(fd, buf, wrlen);
  6432. #else
  6433. cc = write(fd,buf,wrlen);
  6434. #endif /* TCPIPLIB */
  6435. if (cc < 0) {
  6436. int s_errno = socket_errno;
  6437. debug(F101,"net_write error","",s_errno);
  6438. #ifdef OS2
  6439. if (os2socketerror(s_errno) < 0)
  6440. return(-1);
  6441. else
  6442. continue;
  6443. #else /* OS2 */
  6444. if (errno == EINTR)
  6445. continue;
  6446. return(-1);
  6447. #endif /* OS2 */
  6448. }
  6449. else {
  6450. buf += cc;
  6451. wrlen -= cc;
  6452. }
  6453. } while (wrlen > 0);
  6454. return(len);
  6455. }
  6456. int
  6457. net_read(fd, buf, len)
  6458. int fd;
  6459. register char *buf;
  6460. register int len;
  6461. {
  6462. int cc, len2 = 0;
  6463. do {
  6464. #ifdef TCPIPLIB
  6465. cc = socket_read(fd, buf, len);
  6466. #else
  6467. cc = read(fd,buf,len);
  6468. #endif
  6469. if (cc < 0) {
  6470. int s_errno = socket_errno;
  6471. debug(F101,"net_read error","",s_errno);
  6472. #ifdef OS2
  6473. if (os2socketerror(s_errno) < 0)
  6474. return(-1);
  6475. #endif /* OS2 */
  6476. return(cc); /* errno is already set */
  6477. }
  6478. else if (cc == 0) {
  6479. netclos();
  6480. return(len2);
  6481. } else {
  6482. buf += cc;
  6483. len2 += cc;
  6484. len -= cc;
  6485. }
  6486. } while (len > 0);
  6487. return(len2);
  6488. }
  6489. #endif /* CK_KERBEROS */
  6490. #endif /* NONET */
  6491. /* getlocalipaddr() attempts to resolve an IP Address for the local machine.
  6492. * If the host is multi-homed it returns only one address.
  6493. *
  6494. * Two techniques are used.
  6495. * (1) get the local host name and perform a DNS lookup, then take
  6496. * the first entry;
  6497. * (2) open a UDP socket, use it to connect to a fictitious host (it's OK,
  6498. * no data is sent), then retrieve the local address from the socket.
  6499. * Note: the second technique won't work on Microsoft systems. See
  6500. * Article ID: Q129065 PRB: Getsockname() Returns IP Address 0.0.0.0 for UDP
  6501. */
  6502. /* Technique number one cannot work reliably if the machine is a laptop
  6503. * and the hostname is associated with a physical adapter which is not
  6504. * installed and a PPP connection is being used instead. This is because
  6505. * the hostname DNS lookup will succeed for the physical adapter even though
  6506. * it would be impossible to use it. In NT4 SP4, the gethostbyname()
  6507. * when given the result of gethostname() returns not the real DNS entries
  6508. * for that name+domain. Instead it returns all of the static and dynamic
  6509. * IP addresses assigned to any physical or virtual adapter defined in the
  6510. * system regardless of whether or not it is installed. The order of the
  6511. * addresses is fixed according to the binding order in the NT registry.
  6512. */
  6513. /*
  6514. * It appears that calling gethostbyname(NULL) is more reliable than
  6515. * calling gethostbyname(gethostname()) on Windows. So on Windows we will
  6516. * only call gethostbyname(NULL).
  6517. */
  6518. int
  6519. getlocalipaddr() {
  6520. #ifndef datageneral
  6521. struct sockaddr_in l_sa;
  6522. struct sockaddr_in r_sa;
  6523. GSOCKNAME_T slen = sizeof(struct sockaddr_in);
  6524. int sock;
  6525. int rc;
  6526. struct in_addr laddr;
  6527. /* if still not resolved, then try second strategy */
  6528. /* This second strategy does not work on Windows */
  6529. debug(F100,"getlocalipaddr","",0);
  6530. memset(&l_sa,0,slen);
  6531. memset(&r_sa,0,slen);
  6532. /* get a UDP socket */
  6533. sock = socket(AF_INET, SOCK_DGRAM, 0);
  6534. if (sock != -1) {
  6535. /* connect to arbirary port and address (NOT loopback) */
  6536. r_sa.sin_family = AF_INET;
  6537. r_sa.sin_port = htons(IPPORT_ECHO);
  6538. /* The following is an "illegal conversion" in AOS/VS */
  6539. /* (and who knows where else) */
  6540. #ifdef INADDRX
  6541. inaddrx = inet_addr("128.127.50.1");
  6542. r_sa.sin_addr.s_addr = *(unsigned long *)&inaddrx;
  6543. #else
  6544. r_sa.sin_addr.s_addr = inet_addr("128.127.50.1");
  6545. #endif /* INADDRX */
  6546. rc = connect(sock, (struct sockaddr *) &r_sa, sizeof(struct sockaddr));
  6547. if (!rc) { /* get local address */
  6548. getsockname(sock,(struct sockaddr *)&l_sa,&slen);
  6549. #ifdef TCPIPLIB
  6550. socket_close(sock); /* We're done with the socket */
  6551. #else
  6552. close(sock);
  6553. #endif /* TCPIPLIB */
  6554. if (l_sa.sin_addr.s_addr != INADDR_ANY) {
  6555. myxipaddr = ntohl(l_sa.sin_addr.s_addr);
  6556. ckstrncpy(myipaddr,(char *)inet_ntoa(l_sa.sin_addr),20);
  6557. debug(F110,"getlocalipaddr setting buf to",myipaddr,0);
  6558. return(0);
  6559. }
  6560. }
  6561. }
  6562. return getlocalipaddrs(myipaddr,sizeof(myipaddr),0);
  6563. #else /* datageneral */
  6564. return(-1);
  6565. #endif /* datageneral */
  6566. }
  6567. int
  6568. getlocalipaddrs(buf,bufsz,index)
  6569. char * buf;
  6570. int bufsz;
  6571. int index;
  6572. /* getlocalipaddrs */ {
  6573. #ifndef datageneral
  6574. char localhost[256];
  6575. struct hostent * host=NULL;
  6576. struct sockaddr_in l_sa;
  6577. struct sockaddr_in r_sa;
  6578. GSOCKNAME_T slen = sizeof(struct sockaddr_in);
  6579. int rc;
  6580. #ifdef COMMENT
  6581. int sock;
  6582. char messageBuf[60];
  6583. struct in_addr laddr;
  6584. #endif /* COMMENT */
  6585. debug(F100,"getlocalipaddrs","",0);
  6586. memset(&l_sa,0,slen);
  6587. memset(&r_sa,0,slen);
  6588. /* init local address (to zero) */
  6589. l_sa.sin_addr.s_addr = INADDR_ANY;
  6590. #ifdef CKGHNLHOST
  6591. rc = gethostname(localhost, 256);
  6592. debug(F110,"getlocalipaddrs localhost",localhost,0);
  6593. #else
  6594. /* This doesn't work on some platforms, e.g. Solaris */
  6595. rc = 0;
  6596. localhost[0] = '\0';
  6597. #ifdef NT
  6598. if ( winsock_version < 20 ) {
  6599. rc = gethostname(localhost, 256);
  6600. debug(F110,"getlocalipaddrs localhost",localhost,0);
  6601. }
  6602. #endif /* NT */
  6603. #endif /* CKGHNLHOST */
  6604. if (!rc) {
  6605. /* resolve host name for local address */
  6606. debug(F110,"getlocalipaddrs","calling gethostbyname()",0);
  6607. host = gethostbyname(localhost);
  6608. /* debug(F111,"getlocalipaddrs","gethostbyname() returned",host); */
  6609. if (host) {
  6610. #ifdef HADDRLIST
  6611. host = ck_copyhostent(host);
  6612. if ( index < 0 || index > 63 || !host->h_addr_list[index] ) {
  6613. buf[0] = '\0';
  6614. return(-1);
  6615. }
  6616. l_sa.sin_addr.s_addr =
  6617. *((unsigned long *) (host->h_addr_list[index]));
  6618. ckstrncpy(buf,(char *)inet_ntoa(l_sa.sin_addr),20);
  6619. debug(F110,"getlocalipaddrs setting buf to",buf,0);
  6620. #ifdef COMMENT
  6621. /* This is for reporting multiple IP Address */
  6622. while (host->h_addr_list && host->h_addr_list[0]) {
  6623. l_sa.sin_addr.s_addr =
  6624. *((unsigned long *) (host->h_addr_list[0]));
  6625. ckstrncpy(messageBuf,
  6626. (char *)inet_ntoa(l_sa.sin_addr),60);
  6627. if (tcp_address) {
  6628. if (!strcmp(messageBuf,tcp_address))
  6629. ckstrncpy(myipaddr,tcp_address,20);
  6630. }
  6631. debug(F110,"getlocalipaddrs ip address list", messageBuf, 0);
  6632. host->h_addr_list++;
  6633. }
  6634. #endif /* COMMENT */
  6635. #else /* HADDRLIST */
  6636. if (index != 0) {
  6637. buf[0] = '\0';
  6638. return(-1);
  6639. }
  6640. l_sa.sin_addr.s_addr = *((unsigned long *) (host->h_addr));
  6641. ckstrncpy(buf,(char *)inet_ntoa(l_sa.sin_addr),bufsz);
  6642. debug(F110,"getlocalipaddrs setting buf to",buf,0);
  6643. #endif /* HADDRLIST */
  6644. return(0);
  6645. } else debug(F110,
  6646. "getlocalipaddrs: gethostbyname() failed",
  6647. localhost,
  6648. 0
  6649. );
  6650. }
  6651. #endif /* datageneral */
  6652. return(-1);
  6653. }
  6654. #ifdef RLOGCODE /* TCP/IP RLOGIN protocol support code */
  6655. int
  6656. rlog_naws() {
  6657. struct rlog_naws {
  6658. unsigned char id[4];
  6659. unsigned short rows, cols, ypix, xpix;
  6660. } nawsbuf;
  6661. if (ttnet != NET_TCPB)
  6662. return 0;
  6663. if (ttnproto != NP_RLOGIN
  6664. #ifdef CK_KERBEROS
  6665. && ttnproto != NP_K4LOGIN
  6666. && ttnproto != NP_EK4LOGIN
  6667. && ttnproto != NP_K5LOGIN
  6668. && ttnproto != NP_EK5LOGIN
  6669. #endif /* CK_KERBEROS */
  6670. )
  6671. return 0;
  6672. if (!TELOPT_ME(TELOPT_NAWS))
  6673. return 0;
  6674. debug(F100,"rlogin Window Size sent","",0);
  6675. nawsbuf.id[0] = nawsbuf.id[1] = 0377;
  6676. nawsbuf.id[2] = nawsbuf.id[3] = 's';
  6677. #ifdef OS2
  6678. nawsbuf.rows = htons((unsigned short) (VscrnGetHeight(VTERM)
  6679. -(tt_status[VTERM]?1:0)));
  6680. nawsbuf.cols = htons((unsigned short) VscrnGetWidth(VTERM));
  6681. #else /* OS2 */
  6682. nawsbuf.rows = htons((unsigned short) tt_rows);
  6683. nawsbuf.cols = htons((unsigned short) tt_cols);
  6684. #endif /* OS2 */
  6685. nawsbuf.ypix = htons(0); /* y pixels */
  6686. nawsbuf.xpix = htons(0); /* x pixels */
  6687. if (ttol((CHAR *)(&nawsbuf), sizeof(nawsbuf)) < 0)
  6688. return(-1);
  6689. return(0);
  6690. }
  6691. #ifdef OS2ORUNIX
  6692. #define RLOGOUTBUF
  6693. #endif /* OS2 */
  6694. static int
  6695. #ifdef CK_ANSIC
  6696. rlog_ini(CHAR * hostname, int port,
  6697. struct sockaddr_in * l_addr, struct sockaddr_in * r_addr)
  6698. #else /* CK_ANSIC */
  6699. rlog_ini(hostname, port, l_addr, r_addr)
  6700. CHAR * hostname;
  6701. int port;
  6702. struct sockaddr_in * l_addr;
  6703. struct sockaddr_in * r_addr;
  6704. #endif /* CK_ANSIC */
  6705. /* rlog_ini */ {
  6706. #ifdef RLOGOUTBUF
  6707. char outbuf[512];
  6708. int outbytes=0;
  6709. #endif /* RLOGOUTBUF */
  6710. int flag = 0;
  6711. #define TERMLEN 16
  6712. #define CONSPDLEN 16
  6713. CHAR localuser[UIDBUFLEN+1];
  6714. CHAR remoteuser[UIDBUFLEN+1];
  6715. int userlen = 0;
  6716. CHAR term_speed[TERMLEN+CONSPDLEN+1];
  6717. #ifdef CONGSPD
  6718. long conspd = -1L;
  6719. #endif /* CONGSPD */
  6720. #ifdef OS2
  6721. extern int tt_type, max_tt;
  6722. extern struct tt_info_rec tt_info[];
  6723. #endif /* OS2 */
  6724. int i, n;
  6725. int rc = 0;
  6726. tn_reset(); /* This call will reset all of the Telnet */
  6727. /* options and then quit. We need to do */
  6728. /* this since we use the Telnet options */
  6729. /* to hold various state information */
  6730. duplex = 0; /* Rlogin is always remote echo */
  6731. rlog_inband = 0;
  6732. #ifdef CK_TTGWSIZ
  6733. /*
  6734. But compute the values anyway before the first read since the out-
  6735. of-band NAWS request would arrive before the first data byte (NULL).
  6736. */
  6737. #ifdef OS2
  6738. /* Console terminal screen rows and columns */
  6739. debug(F101,"rlog_ini tt_rows 1","",VscrnGetHeight(VTERM)
  6740. -(tt_status[VTERM]?1:0));
  6741. debug(F101,"rlog_ini tt_cols 1","",VscrnGetWidth(VTERM));
  6742. /* Not known yet */
  6743. if (VscrnGetWidth(VTERM) < 0 ||
  6744. VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) < 0) {
  6745. ttgwsiz(); /* Try to get screen dimensions */
  6746. }
  6747. debug(F101,
  6748. "rlog_ini tt_rows 2",
  6749. "",
  6750. VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
  6751. );
  6752. debug(F101,"rlog_ini tt_cols 2","",VscrnGetWidth(VTERM));
  6753. #else /* OS2 */
  6754. debug(F101,"rlog_ini tt_rows 1","",tt_rows);
  6755. debug(F101,"rlog_ini tt_cols 1","",tt_cols);
  6756. if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
  6757. ttgwsiz(); /* Try to find out */
  6758. }
  6759. debug(F101,"rlog_ini tt_rows 2","",tt_rows);
  6760. debug(F101,"rlog_ini tt_cols 2","",tt_cols);
  6761. #endif /* OS2 */
  6762. #endif /* CK_TTGWSIZ */
  6763. ttflui(); /* Start by flushing the buffers */
  6764. rlog_mode = RL_COOKED;
  6765. /* Determine the user's local username ... */
  6766. localuser[0] = '\0';
  6767. #ifdef NT
  6768. {
  6769. char localuid[UIDBUFLEN+1];
  6770. ckstrncpy((char *)localuser,(char *)GetLocalUser(),UIDBUFLEN);
  6771. }
  6772. if ( !localuser[0] )
  6773. #endif /* NT */
  6774. {
  6775. char * user = getenv("USER");
  6776. if (!user)
  6777. user = "";
  6778. userlen = strlen(user);
  6779. debug(F111,"rlogin getenv(USER)",user,userlen);
  6780. ckstrncpy((char *)localuser,user,UIDBUFLEN);
  6781. debug(F110,"rlog_ini localuser 1",localuser,0);
  6782. }
  6783. if ( !localuser[0] )
  6784. strcpy((char *)localuser,"unknown");
  6785. else if (ck_lcname) {
  6786. cklower((char *)localuser);
  6787. debug(F110,"rlog_ini localuser 2",localuser,0);
  6788. }
  6789. /* And the username to login with */
  6790. if (uidbuf[0]) {
  6791. ckstrncpy((char *)remoteuser,uidbuf,UIDBUFLEN);
  6792. debug(F110,"rlog_ini remoteuser 1",remoteuser,0);
  6793. } else if (localuser[0]) {
  6794. ckstrncpy((char *)remoteuser,(char *)localuser,UIDBUFLEN);
  6795. debug(F110,"rlog_ini remoteuser 2",remoteuser,0);
  6796. } else {
  6797. remoteuser[0] = '\0';
  6798. debug(F110,"rlog_ini remoteuser 3",remoteuser,0);
  6799. }
  6800. if (ck_lcname)
  6801. cklower((char *)remoteuser);
  6802. debug(F110,"rlog_ini remoteuser 4",remoteuser,0);
  6803. /* The command to issue is the terminal type and speed */
  6804. term_speed[0] = '\0';
  6805. if (tn_term) { /* SET TELNET TERMINAL-TYPE value */
  6806. if (*tn_term) { /* (if any) takes precedence. */
  6807. ckstrncpy((char *)term_speed, tn_term, TERMLEN);
  6808. flag = 1;
  6809. }
  6810. } else { /* Otherwise the local terminal type */
  6811. #ifdef OS2
  6812. /* In terminal-emulating versions, it's the SET TERM TYPE value */
  6813. ckstrncpy(term_speed, (tt_type >= 0 && tt_type <= max_tt) ?
  6814. tt_info[tt_type].x_name : "network", TERMLEN);
  6815. #else
  6816. /* In the others, we just look at the TERM environment variable */
  6817. {
  6818. char *p = getenv("TERM");
  6819. if (p)
  6820. ckstrncpy((char *)term_speed,p,TERMLEN);
  6821. else
  6822. term_speed[0] = '\0';
  6823. #ifdef VMS
  6824. for (p = (char *) term_speed; *p; p++) {
  6825. if (*p == '-' && (!strcmp(p,"-80") || !strcmp(p,"-132")))
  6826. break;
  6827. else if (isupper(*p))
  6828. *p = tolower(*p);
  6829. }
  6830. *p = '\0';
  6831. #endif /* VMS */
  6832. }
  6833. #endif /* OS2 */
  6834. }
  6835. n = strlen((char *)term_speed);
  6836. if (n > 0) { /* We have a terminal type */
  6837. if (!flag) { /* If not user-specified */
  6838. for (i = 0; i < n; i++) /* then lowercase it. */
  6839. if (isupper(term_speed[i]))
  6840. term_speed[i] = tolower(term_speed[i]);
  6841. }
  6842. debug(F110,"rlog_ini term_speed 1",term_speed,0);
  6843. #ifdef CONGSPD
  6844. /* conspd() is not yet defined in all ck*tio.c modules */
  6845. conspd = congspd();
  6846. if (conspd > 0L) {
  6847. ckstrncat((char *)term_speed,"/",sizeof(term_speed));
  6848. ckstrncat((char *)term_speed,ckltoa(conspd),sizeof(term_speed));
  6849. } else
  6850. #endif /* CONGSPD */
  6851. ckstrncat((char *)term_speed,"/19200",sizeof(term_speed));
  6852. debug(F110,"rlog_ini term_speed 2",term_speed,0);
  6853. } else {
  6854. term_speed[0] = '\0';
  6855. debug(F110,"rlog_ini term_speed 3",term_speed,0);
  6856. }
  6857. #ifdef CK_KERBEROS
  6858. if (ttnproto == NP_K4LOGIN || ttnproto == NP_EK4LOGIN ||
  6859. ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN) {
  6860. int kver, encrypt, rc;
  6861. switch (ttnproto) {
  6862. case NP_K4LOGIN:
  6863. kver = 4;
  6864. encrypt = 0;
  6865. break;
  6866. case NP_EK4LOGIN:
  6867. kver = 4;
  6868. encrypt = 1;
  6869. break;
  6870. case NP_K5LOGIN:
  6871. kver = 5;
  6872. encrypt = 0;
  6873. break;
  6874. case NP_EK5LOGIN:
  6875. kver = 5;
  6876. encrypt = 1;
  6877. break;
  6878. default:
  6879. kver = 0;
  6880. encrypt = 0;
  6881. }
  6882. rc = ck_krb_rlogin(hostname, port,
  6883. localuser, remoteuser, term_speed,
  6884. l_addr, r_addr, kver, encrypt);
  6885. if (!rc) { /* success */
  6886. TELOPT_ME(TELOPT_NAWS) = 1;
  6887. rc = rlog_naws();
  6888. }
  6889. return(rc);
  6890. } else
  6891. #endif /* CK_KERBEROS */
  6892. if (ttnproto == NP_RLOGIN) {
  6893. #ifdef RLOGOUTBUF
  6894. /*
  6895. * The rcmds start the connection with a series of init data:
  6896. *
  6897. * a port number upon which client is listening for stderr data
  6898. * the user's name on the client machine
  6899. * the user's name on the server machine
  6900. * the terminal_type/speed or command to execute
  6901. */
  6902. outbuf[outbytes++] = 0;
  6903. strcpy((char *)outbuf+outbytes,(char *)localuser);
  6904. outbytes += strlen((char *)localuser) + 1;
  6905. strcpy((char *)outbuf+outbytes,(char *)remoteuser);
  6906. outbytes += strlen((char *)remoteuser) + 1;
  6907. strcpy((char *)outbuf+outbytes,(char *)term_speed);
  6908. outbytes += strlen((char *)term_speed) + 1;
  6909. rc = ttol((CHAR *)outbuf,outbytes);
  6910. #else /* RLOGOUTBUF */
  6911. ttoc(0); /* Send an initial NUL as wake-up */
  6912. /* Send each variable with the trailing NUL */
  6913. rc = ttol(localuser,strlen((char *)localuser)+1);
  6914. if (rc > 0)
  6915. rc = ttol(remoteuser,strlen((char *)remoteuser)+1);
  6916. if (rc > 0)
  6917. rc = ttol(term_speed,strlen((char *)term_speed)+1);
  6918. #endif /* RLOGOUTBUF */
  6919. /* Now we are supposed to get back a single NUL as confirmation */
  6920. errno = 0;
  6921. rc = ttinc(60);
  6922. debug(F101,"rlogin first ttinc","",rc);
  6923. if (rc > 0) {
  6924. debug(F101,"rlogin ttinc 1","",rc);
  6925. printf(
  6926. "Rlogin protocol error - 0x%x received instead of 0x00\n", rc);
  6927. return(-1);
  6928. } else if (rc < 0) {
  6929. debug(F101,"rlogin ttinc errno","",errno);
  6930. /* printf("Network error: %d\n", errno); */
  6931. return(-1);
  6932. }
  6933. }
  6934. return(0);
  6935. }
  6936. /* two control messages are defined:
  6937. a double flag byte of 'o' indicates a one-byte message which is
  6938. identical to what was once carried out of band.
  6939. a double flag byte of 'q' indicates a zero-byte message. This
  6940. message is interpreted as two \377 data bytes. This is just a
  6941. quote rule so that binary data from the server does not confuse the
  6942. client. */
  6943. int
  6944. rlog_ctrl(cp, n)
  6945. unsigned char *cp;
  6946. int n;
  6947. {
  6948. if ((n >= 5) && (cp[2] == 'o') && (cp[3] == 'o')) {
  6949. if (rlog_oob(&cp[4],1))
  6950. return(-5);
  6951. return(5);
  6952. } else if ((n >= 4) && (cp[2] == 'q') && (cp[3] == 'q')) {
  6953. /* this is somewhat of a hack */
  6954. cp[2] = '\377';
  6955. cp[3] = '\377';
  6956. return(2);
  6957. }
  6958. return(0);
  6959. }
  6960. static int
  6961. rlog_oob(oobdata, count) CHAR * oobdata; int count; {
  6962. int i;
  6963. int flush = 0;
  6964. debug(F111,"rlogin out_of_band","count",count);
  6965. for (i = 0; i<count; i++) {
  6966. debug(F101,"rlogin out_of_band","",oobdata[i]);
  6967. if (oobdata[i] & 0x01)
  6968. continue;
  6969. if (oobdata[i] & 0x02) { /* Flush Buffered Data not yet displayed */
  6970. debug(F101,"rlogin Flush Buffered Data command","",oobdata[i]);
  6971. /* Only flush the data if in fact we are in a mode that won't */
  6972. /* get out of sync. Ie, not when we are in protocol mode. */
  6973. switch ( what ) {
  6974. case W_NOTHING:
  6975. case W_CONNECT:
  6976. case W_COMMAND:
  6977. if ( rlog_inband )
  6978. flush = 1;
  6979. else
  6980. ttflui();
  6981. break;
  6982. }
  6983. }
  6984. if (oobdata[i] & 0x10) { /* Switch to RAW mode */
  6985. debug(F101,"rlogin Raw Mode command","",oobdata[i]);
  6986. rlog_mode = RL_RAW;
  6987. }
  6988. if (oobdata[i] & 0x20) { /* Switch to COOKED mode */
  6989. debug(F101,"rlogin Cooked Mode command","",oobdata[i]);
  6990. rlog_mode = RL_COOKED;
  6991. }
  6992. if (oobdata[i] & 0x80)
  6993. { /* Send Window Size Info */
  6994. debug(F101,"rlogin Window Size command","",oobdata[i]);
  6995. /* Remember to send WS Info when Window Size changes */
  6996. if ( !TELOPT_ME(TELOPT_NAWS) ) {
  6997. TELOPT_ME(TELOPT_NAWS) = 1;
  6998. rlog_naws();
  6999. }
  7000. }
  7001. }
  7002. return(flush);
  7003. }
  7004. #ifndef TCPIPLIB
  7005. static SIGTYP
  7006. rlogoobh(sig) int sig; {
  7007. #ifdef SOLARIS
  7008. char /* Or should it be char for all? */
  7009. #else
  7010. CHAR
  7011. #endif /* SOLARIS */
  7012. oobdata;
  7013. /* int count = 0; */ /* (not used) */
  7014. while (recv(ttyfd, &oobdata, 1, MSG_OOB) < 0) {
  7015. /*
  7016. * We need to do some special processing here.
  7017. * Just in case the socket is blocked for input
  7018. *
  7019. */
  7020. switch (errno) {
  7021. case EWOULDBLOCK:
  7022. break;
  7023. default:
  7024. return;
  7025. }
  7026. }
  7027. debug(F101,"rlogin out_of_band","",oobdata);
  7028. if (oobdata == 0x02) { /* Flush Buffered Data not yet displayed */
  7029. debug(F101,"rlogin Flush Buffered Data command","",oobdata);
  7030. netflui();
  7031. }
  7032. if (oobdata & 0x10) { /* Switch to raw mode */
  7033. debug(F101,"rlogin Raw Mode command","",oobdata);
  7034. rlog_mode = RL_RAW;
  7035. }
  7036. if (oobdata & 0x20) { /* Switch to cooked mode */
  7037. debug(F101,"rlogin Cooked Mode command","",oobdata);
  7038. rlog_mode = RL_COOKED;
  7039. }
  7040. if (oobdata & 0x80) { /* Send Window Size Info */
  7041. debug(F101,"rlogin Window Size command","",oobdata);
  7042. /* Remember to send WS Info when Window Size changes */
  7043. if ( !TELOPT_ME(TELOPT_NAWS) ) {
  7044. TELOPT_ME(TELOPT_NAWS) = 1;
  7045. rlog_naws();
  7046. }
  7047. }
  7048. }
  7049. #endif /* TCPIPLIB */
  7050. #endif /* RLOGCODE */
  7051. /* Send network BREAK */
  7052. /*
  7053. Returns -1 on error, 0 if nothing happens, 1 if BREAK sent successfully.
  7054. */
  7055. int
  7056. netbreak() {
  7057. CHAR buf[3];
  7058. if (ttnet == NET_TCPB) {
  7059. if (ttnproto == NP_TELNET) {
  7060. #ifdef TNCODE
  7061. buf[0] = (CHAR) IAC; buf[1] = (CHAR) BREAK; buf[2] = (CHAR) 0;
  7062. if (
  7063. #ifdef OS2
  7064. nettol((char *) buf, 2)
  7065. #else
  7066. ttol(buf, 2)
  7067. #endif /* OS2 */
  7068. < 2)
  7069. return(-1);
  7070. if (tn_deb || debses || deblog) {
  7071. extern char tn_msg[];
  7072. ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET SENT ",TELCMD(BREAK),
  7073. NULL,NULL);
  7074. debug(F101,tn_msg,"",BREAK);
  7075. if (debses || tn_deb) tn_debug(tn_msg);
  7076. }
  7077. return(1);
  7078. #else
  7079. debug(F100,"netbreak no TNCODE","",0);
  7080. return(0);
  7081. #endif /* TNCODE */
  7082. }
  7083. /* Insert other TCP/IP protocols here */
  7084. }
  7085. /* Insert other networks here */
  7086. return(0);
  7087. }
  7088. #endif /* NETCONN */
  7089. #ifdef NETCONN
  7090. #ifdef SUNX25
  7091. /*
  7092. SunLink X.25 support by Marcello Frutig, Catholic University,
  7093. Rio de Janeiro, Brazil, 1990.
  7094. */
  7095. /* PAD X.3, X.28 and X.29 support */
  7096. static CHAR x29err[MAXPADPARMS+3] = { X29_ERROR, INVALID_PAD_PARM, '\0' };
  7097. /* Initialize PAD */
  7098. extern CHAR padparms[];
  7099. VOID
  7100. initpad() {
  7101. padparms[PAD_BREAK_CHARACTER] = 0; /* Break character */
  7102. padparms[PAD_ESCAPE] = 1; /* Escape permitted */
  7103. padparms[PAD_ECHO] = 1; /* Kermit PAD does echo */
  7104. padparms[PAD_DATA_FORWARD_CHAR] = 2; /* forward character CR */
  7105. padparms[PAD_DATA_FORWARD_TIMEOUT] = 0; /* no timeout forward condition */
  7106. padparms[PAD_FLOW_CONTROL_BY_PAD] = 0; /* not used */
  7107. padparms[PAD_SUPPRESSION_OF_SIGNALS] = 1; /* allow PAD service signals */
  7108. padparms[PAD_BREAK_ACTION] = 21; /* brk action: INT pk + brk ind*/
  7109. padparms[PAD_SUPPRESSION_OF_DATA] = 0; /* no supression of user data */
  7110. padparms[PAD_PADDING_AFTER_CR] = 0; /* no padding after CR */
  7111. padparms[PAD_LINE_FOLDING] = 0; /* no line fold */
  7112. padparms[PAD_LINE_SPEED] = 0; /* line speed - don't care */
  7113. padparms[PAD_FLOW_CONTROL_BY_USER] = 0; /* flow cont of PAD - not used */
  7114. padparms[PAD_LF_AFTER_CR] = 0; /* no LF insertion after CR */
  7115. padparms[PAD_PADDING_AFTER_LF] = 0; /* no padding after LF */
  7116. padparms[PAD_EDITING] = 1; /* can edit */
  7117. padparms[PAD_CHAR_DELETE_CHAR] = 8; /* character delete character */
  7118. padparms[PAD_BUFFER_DELETE_CHAR] = 21; /* buffer delete character */
  7119. padparms[PAD_BUFFER_DISPLAY_CHAR] = 18; /* buffer display character */
  7120. }
  7121. /* Set PAD parameters */
  7122. VOID
  7123. setpad(s,n) CHAR *s; int n; {
  7124. int i;
  7125. CHAR *ps = s;
  7126. if (n < 1) {
  7127. initpad();
  7128. } else {
  7129. for (i = 0; i < n; i++) {
  7130. if (*ps > MAXPADPARMS)
  7131. x29err[i+2] = *ps;
  7132. else
  7133. padparms[*ps] = *(ps+1);
  7134. ps += 2;
  7135. }
  7136. }
  7137. }
  7138. /* Read PAD parameters */
  7139. VOID
  7140. readpad(s,n,r) CHAR *s; int n; CHAR *r; {
  7141. int i;
  7142. CHAR *ps = s;
  7143. CHAR *pr = r;
  7144. *pr++ = X29_PARAMETER_INDICATION;
  7145. if (n > 0) {
  7146. for (i = 0; i < n; i++, ps++) {
  7147. if (*ps > MAXPADPARMS) {
  7148. x29err[i+2] = *ps++;
  7149. } else {
  7150. *pr++ = *ps;
  7151. *pr++ = padparms[*ps++];
  7152. }
  7153. }
  7154. } else {
  7155. for (i = 1; i < MAXPADPARMS; i++) {
  7156. *pr++ = i;
  7157. *pr++ = padparms[i];
  7158. }
  7159. }
  7160. }
  7161. int
  7162. qbitpkt(s,n) CHAR *s; int n; {
  7163. CHAR *ps = s;
  7164. int x29cmd = *ps;
  7165. CHAR *psa = s+1;
  7166. CHAR x29resp[(MAXPADPARMS*2)+1];
  7167. switch (x29cmd) {
  7168. case X29_SET_PARMS:
  7169. setpad (ps+1,n/2);
  7170. if ((int)strlen((char *)x29err) > 2) {
  7171. ttol(x29err,(int)strlen((char *)x29err));
  7172. x29err[2] = '\0';
  7173. }
  7174. return (-2);
  7175. case X29_READ_PARMS:
  7176. readpad (ps+1,n/2,x29resp);
  7177. setqbit ();
  7178. ttol(x29resp,(n>1)?(n+1):(2*MAXPADPARMS+1));
  7179. if ((int)strlen((char *)x29err) > 2) {
  7180. ttol(x29err,(int)strlen((char *)x29err));
  7181. x29err[2] = '\0';
  7182. }
  7183. resetqbit();
  7184. break;
  7185. case X29_SET_AND_READ_PARMS:
  7186. setpad (ps+1,n/2);
  7187. readpad (ps+1,n/2,x29resp);
  7188. setqbit();
  7189. ttol(x29resp,(n>1)?(n+1):(2*MAXPADPARMS+1));
  7190. if ((int)strlen((char *)x29err) > 2) {
  7191. ttol (x29err,(int)strlen((char *)x29err));
  7192. x29err [2] = '\0';
  7193. }
  7194. resetqbit();
  7195. return (-2);
  7196. case X29_INVITATION_TO_CLEAR:
  7197. (VOID) x25clear();
  7198. return (-1);
  7199. case X29_INDICATION_OF_BREAK:
  7200. break;
  7201. }
  7202. return (0);
  7203. }
  7204. /* PAD break action processor */
  7205. VOID
  7206. breakact() {
  7207. extern char x25obuf[MAXOX25];
  7208. extern int obufl;
  7209. extern int active;
  7210. extern unsigned char tosend;
  7211. static CHAR indbrk[3] = {
  7212. X29_INDICATION_OF_BREAK,
  7213. PAD_SUPPRESSION_OF_DATA,
  7214. 1
  7215. };
  7216. CHAR intudat, cause, diag;
  7217. if (x25stat() < 0) return; /* Ignore if no virtual call established */
  7218. if (padparms[PAD_BREAK_ACTION] != 0) /* Forward condition */
  7219. if (ttol((CHAR *)x25obuf,obufl) < 0) {
  7220. perror ("\r\nCan't send characters");
  7221. active = 0;
  7222. } else {
  7223. bzero (x25obuf,sizeof(x25obuf));
  7224. obufl = 0;
  7225. tosend = 0;
  7226. };
  7227. switch (padparms[PAD_BREAK_ACTION]) {
  7228. case 0 : break; /* do nothing */
  7229. case 1 : /* send interrupt packet with interrupt user data field = 1 */
  7230. intudat = 1;
  7231. x25intr (intudat);
  7232. break;
  7233. case 2 : /* send reset packet with cause and diag = 0 */
  7234. cause = diag = 0;
  7235. x25reset (cause,diag);
  7236. break;
  7237. case 5 : /* send interrupt packet with interrupt user data field = 0 */
  7238. intudat = 0;
  7239. x25intr (intudat);
  7240. setqbit ();
  7241. /* send indication of break without a parameter field */
  7242. ttoc(X29_INDICATION_OF_BREAK);
  7243. resetqbit ();
  7244. break;
  7245. case 8 : active = 0; /* leave data transfer */
  7246. conol ("\r\n");
  7247. break;
  7248. case 21: /* send interrupt packet with interrupt user data field = 0 */
  7249. intudat = 0;
  7250. x25intr (intudat);
  7251. setpad (indbrk+1,2); /* set pad to discard input */
  7252. setqbit ();
  7253. /* send indication of break with parameter field */
  7254. ttol (indbrk,sizeof(indbrk));
  7255. resetqbit ();
  7256. break;
  7257. }
  7258. }
  7259. /* X.25 support functions */
  7260. X25_CAUSE_DIAG diag;
  7261. /*
  7262. Convert a null-terminated string representing an X.121 address
  7263. to a packed BCD form.
  7264. */
  7265. int
  7266. pkx121(str,bcd) char *str; CHAR *bcd; {
  7267. int i, j;
  7268. u_char c;
  7269. i = j = 0;
  7270. while (str[i]) {
  7271. if (i >= 15 || str [i] < '0' || str [i] > '9')
  7272. return (-1);
  7273. c = str [i] - '0';
  7274. if (i & 1)
  7275. bcd [j++] |= c;
  7276. else
  7277. bcd [j] = c << 4;
  7278. i++;
  7279. }
  7280. return (i);
  7281. }
  7282. /* Reads and prints X.25 diagnostic */
  7283. int
  7284. x25diag () {
  7285. int i;
  7286. bzero ((char *)&diag,sizeof(diag));
  7287. if (ioctl(ttyfd,X25_RD_CAUSE_DIAG,&diag)) {
  7288. perror ("Reading X.25 diagnostic");
  7289. return(-1);
  7290. }
  7291. if (diag.datalen > 0) {
  7292. printf ("X.25 Diagnostic :");
  7293. for (i = 0; i < (int)diag.datalen; i++)
  7294. printf(" %02h",diag.data[i])+
  7295. printf ("\r\n");
  7296. }
  7297. return(0);
  7298. }
  7299. /* X.25 Out-of-Band Signal Handler */
  7300. SIGTYP
  7301. x25oobh(foo) int foo; {
  7302. int oobtype;
  7303. u_char oobdata;
  7304. int t;
  7305. (VOID) signal(SIGURG,x25oobh);
  7306. do {
  7307. if (ioctl(ttyfd,X25_OOB_TYPE,&oobtype)) {
  7308. perror ("Getting signal type");
  7309. return;
  7310. }
  7311. switch (oobtype) {
  7312. case INT_DATA:
  7313. if (recv(ttyfd,(char *)&oobdata,1,MSG_OOB) < 0) {
  7314. perror ("Receiving X.25 interrupt data");
  7315. return;
  7316. }
  7317. t = oobdata;
  7318. printf ("\r\nInterrupt received, data = %d\r\n", t);
  7319. break;
  7320. case VC_RESET:
  7321. printf ("\r\nVirtual circuit reset\r\n");
  7322. x25diag ();
  7323. break;
  7324. case N_RESETS:
  7325. printf ("\r\nReset timeout\r\n");
  7326. break;
  7327. case N_CLEARS:
  7328. printf ("\r\nClear timeout\r\n");
  7329. break;
  7330. case MSG_TOO_LONG:
  7331. printf ("\r\nMessage discarded, too long\r\n");
  7332. break;
  7333. default:
  7334. if (oobtype) printf("\r\nUnknown oob type %d\r\n",oobtype);
  7335. break;
  7336. }
  7337. } while (oobtype);
  7338. }
  7339. /* Send a X.25 interrupt packet */
  7340. int
  7341. #ifdef CK_ANSIC
  7342. x25intr(char intr)
  7343. #else
  7344. x25intr(intr) char intr;
  7345. #endif /* CK_ANSIC */
  7346. /* x25intr */ {
  7347. if (send(ttyfd,&intr,1,MSG_OOB) < 0) return(-1);
  7348. debug(F100,"X.25 intr","",0);
  7349. return(0);
  7350. }
  7351. /* Reset X.25 virtual circuit */
  7352. int
  7353. #ifdef CK_ANSIC
  7354. x25reset(char cause, char diagn)
  7355. #else
  7356. x25reset(cause, diagn) char cause; char diagn;
  7357. #endif /* CK_ANSIC */
  7358. /* x25reset */ {
  7359. bzero ((char *)&diag,sizeof(diag));
  7360. diag.flags = 0;
  7361. diag.datalen = 2;
  7362. diag.data[0] = cause;
  7363. diag.data[1] = diagn;
  7364. if (ioctl(ttyfd,X25_WR_CAUSE_DIAG,&diag) < 0)
  7365. return(-1);
  7366. debug(F100,"X.25 reset","",0);
  7367. return(0);
  7368. }
  7369. /* Clear X.25 virtual circuit */
  7370. int
  7371. x25clear() {
  7372. int i;
  7373. debug(F100,"X.25 clear","",0);
  7374. bzero ((char *)&diag,sizeof(diag));
  7375. diag.flags = (1 << DIAG_TYPE);
  7376. diag.datalen = 2;
  7377. diag.data[0] = 0;
  7378. diag.data[1] = 0;
  7379. ioctl (ttyfd,X25_WR_CAUSE_DIAG,&diag); /* Send Clear Request */
  7380. return(ttclos(0)); /* Close socket */
  7381. }
  7382. /* X.25 status */
  7383. int
  7384. x25stat() {
  7385. if (ttyfd == -1) return (-1);
  7386. return(0);
  7387. }
  7388. /* Set Q_BIT on */
  7389. VOID
  7390. setqbit() {
  7391. static int qbiton = 1 << Q_BIT;
  7392. ioctl (ttyfd,X25_SEND_TYPE,&qbiton);
  7393. }
  7394. /* Set Q_BIT off */
  7395. VOID
  7396. resetqbit() {
  7397. static int qbitoff = 0;
  7398. ioctl (ttyfd,X25_SEND_TYPE,&qbitoff);
  7399. }
  7400. /* Read n characters from X.25 circuit into buf */
  7401. int
  7402. x25xin(n,buf) int n; CHAR *buf; {
  7403. register int x, c;
  7404. int qpkt;
  7405. do {
  7406. x = read(ttyfd,buf,n);
  7407. if (buf[0] & (1 << Q_BIT)) { /* If Q_BIT packet, process it */
  7408. /* If return -1 : invitation to clear; -2 : PAD changes */
  7409. if ((c=qbitpkt(buf+1,x-2)) < 0) return(c);
  7410. qpkt = 1;
  7411. } else qpkt = 0;
  7412. } while (qpkt);
  7413. #ifdef COMMENT /* Disabled by Stephen Riehm 19.12.97 */
  7414. /* BUG!
  7415. * if buf[] is full, then this null lands in nirvana!
  7416. * I was unable to find any code which needs a trailing null in buf[]
  7417. */
  7418. if (x > 0) buf[x] = '\0';
  7419. #endif /* COMMENT */
  7420. if (x < 1) x = -1;
  7421. debug(F101,"x25xin x","",x);
  7422. return(x);
  7423. }
  7424. #ifdef COMMENT /* NO LONGER NEEDED! */
  7425. /* X.25 read a line */
  7426. int
  7427. #ifdef PARSENSE
  7428. #ifdef CK_ANSIC
  7429. x25inl(CHAR *dest, int max,int timo, CHAR eol, CHAR start)
  7430. #else
  7431. x25inl(dest,max,timo,eol,start) int max,timo; CHAR *dest, eol, start;
  7432. #endif /* CK_ANSIC */
  7433. #else /* not PARSENSE */
  7434. #ifdef CK_ANSIC
  7435. x25inl(CHAR *dest, int max,int timo, CHAR eol)
  7436. #else
  7437. x25inl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
  7438. #endif /* __SDTC__ */
  7439. #endif /*PARSENSE */
  7440. /* x25inl */ {
  7441. CHAR *pdest;
  7442. int pktype, goteol, rest, n;
  7443. int i, flag = 0;
  7444. extern int ttprty, ttpflg;
  7445. int ttpmsk;
  7446. ttpmsk = (ttprty) ? 0177 : 0377; /* Set parity stripping mask */
  7447. debug(F101,"x25inl max","",max);
  7448. debug(F101,"x25inl eol","",eol);
  7449. pdest = dest;
  7450. rest = max;
  7451. goteol = 0;
  7452. do {
  7453. n = read(ttyfd,pdest,rest);
  7454. n--;
  7455. pktype = *pdest & 0x7f;
  7456. switch (pktype) {
  7457. case 1 << Q_BIT:
  7458. if (qbitpkt(pdest+1,--n) < 0) return(-2);
  7459. break;
  7460. default:
  7461. if (flag == 0) { /* if not in packet, search start */
  7462. for (i = 1; (i < n) &&
  7463. !(flag = ((dest[i] & 0x7f) == start));
  7464. i++);
  7465. if (flag == 0) { /* not found, discard junk */
  7466. debug(F101,"x25inl skipping","",n);
  7467. continue;
  7468. } else { /* found, discard junk before start */
  7469. int k;
  7470. n = n - i + 1;
  7471. for (k = 1; k <= n; k++, i++) dest[k] = dest[i];
  7472. }
  7473. }
  7474. for (i = 0; (i < n) && /* search for eol */
  7475. !(goteol=(((*pdest = *(pdest+1)&ttpmsk)&0x7f)== eol));
  7476. i++,pdest++);
  7477. *pdest = '\0';
  7478. rest -= n;
  7479. }
  7480. } while ((rest > 0) && (!goteol));
  7481. if (goteol) {
  7482. n = max - rest;
  7483. debug (F111,"x25inl X.25 got",(char *) dest,n);
  7484. if (timo) ttimoff();
  7485. if (ttpflg++ == 0 && ttprty == 0) {
  7486. if ((ttprty = parchk(dest,start,n)) > 0) {
  7487. int j;
  7488. debug(F101,"x25inl senses parity","",ttprty);
  7489. debug(F110,"x25inl packet before",(char *)dest,0);
  7490. ttpmsk = 0x7f;
  7491. for (j = 0; j < n; j++)
  7492. dest[j] &= 0x7f; /* Strip parity from packet */
  7493. debug(F110,"x25inl packet after ",dest,0);
  7494. } else {
  7495. debug(F101,"parchk","",ttprty);
  7496. if (ttprty < 0) { ttprty = 0; n = -1; }
  7497. }
  7498. }
  7499. ttimoff();
  7500. return(n);
  7501. }
  7502. ttimoff();
  7503. return(-1);
  7504. }
  7505. #endif /* COMMENT */
  7506. #endif /* SUNX25 */
  7507. #ifdef IBMX25
  7508. /*
  7509. * IBM X25 support - using the NPI streams interface
  7510. * written by Stephen Riehm, pc-plus, Munich Germany
  7511. */
  7512. /* riehm: missing functions / TODO list */
  7513. /*
  7514. x25intr() - Send an interrupt packet
  7515. */
  7516. /* return an error message depending on packet type */
  7517. char *
  7518. x25err(n) int n; {
  7519. static char buf[30];
  7520. switch (n) {
  7521. case NBADADDR: return "invalid address";
  7522. case NBADOPT: return "invalid options";
  7523. case NACCESS: return "no permission";
  7524. case NNOADDR: return "unable to allocate address";
  7525. case NOUTSTATE: return "invalid state";
  7526. case NBADSEQ: return "invalid sequence number";
  7527. case NSYSERR: return "system error";
  7528. case NBADDATA: return "invalid data size";
  7529. case NBADFLAG: return "invalid flag";
  7530. case NNOTSUPPORT: return "unsupported primitive";
  7531. case NBOUND: return "address in use";
  7532. case NBADQOSPARAM: return "bad QOS parameters";
  7533. case NBADQOSTYPE: return "bad QOS type";
  7534. case NBADTOKEN: return "bad token value";
  7535. case NNOPROTOID: return "protocol id could not be allocated";
  7536. case NODDCUD: return "odd length call user data";
  7537. default:
  7538. ckmakmsg(buf,sizeof(buf),"Unknown NPI error ",ckitoa(n),NULL,NULL);
  7539. return buf;
  7540. }
  7541. }
  7542. /* turn a meaningless primitive number into a meaningful primitive name */
  7543. char *
  7544. x25prim(n) int n; {
  7545. static char buf[30];
  7546. switch(n) {
  7547. case N_BIND_ACK: return "N_BIND_ACK";
  7548. case N_BIND_REQ: return "N_BIND_REQ";
  7549. case N_CONN_CON: return "N_CONN_CON";
  7550. case N_CONN_IND: return "N_CONN_IND";
  7551. case N_CONN_REQ: return "N_CONN_REQ";
  7552. case N_CONN_RES: return "N_CONN_RES";
  7553. case N_DATACK_IND: return "N_DATAACK_IND";
  7554. case N_DATACK_REQ: return "N_DATAACK_REQ";
  7555. case N_DATA_IND: return "N_DATA_IND";
  7556. case N_DATA_REQ: return "N_DATA_REQ";
  7557. case N_DISCON_IND: return "N_DISCON_IND";
  7558. case N_DISCON_REQ: return "N_DISCON_REQ";
  7559. case N_ERROR_ACK: return "N_ERROR_ACK";
  7560. case N_EXDATA_IND: return "N_EXDATA_IND";
  7561. case N_EXDATA_REQ: return "N_EXDATA_REQ";
  7562. case N_INFO_ACK: return "N_INFO_ACK";
  7563. case N_INFO_REQ: return "N_INFO_REQ";
  7564. case N_OK_ACK: return "N_OK_ACK";
  7565. case N_OPTMGMT_REQ: return "N_OPTMGMT_REQ";
  7566. case N_RESET_CON: return "N_RESET_CON";
  7567. case N_RESET_IND: return "N_RESET_IND";
  7568. case N_RESET_REQ: return "N_RESET_REQ";
  7569. case N_RESET_RES: return "N_RESET_RES";
  7570. case N_UDERROR_IND: return "N_UDERROR_IND";
  7571. case N_UNBIND_REQ: return "N_UNBIND_REQ";
  7572. case N_UNITDATA_REQ: return "N_UNITDATA_REQ";
  7573. case N_UNITDATA_IND: return "N_UNITDATA_IND";
  7574. default:
  7575. ckmakmsg(buf,sizeof(buf),"UNKNOWN (",ckitoa(n),")",NULL);
  7576. return buf;
  7577. }
  7578. }
  7579. /*****************************************************************************
  7580. * Function: x25getmsg()
  7581. * Description: get a STREAMS message, and check it for errors
  7582. *
  7583. * Parameters:
  7584. * fd - file descriptor to x25 device (opened)
  7585. * control - control buffer (pre-allocated)
  7586. * ctl_size - size of control buffer
  7587. * data - data buffer (pre-allocated)
  7588. * data_size - size of data buffer
  7589. * flags - flags for getmsg()
  7590. * expected - expected Primitive type
  7591. *
  7592. * Return Value:
  7593. * >= 0 OK (size of data returned)
  7594. * -1 error
  7595. *
  7596. */
  7597. int
  7598. x25getmsg( fd, control, ctl_size, data, data_size, get_flags, expected )
  7599. int fd; /* X25 device (opened) */
  7600. N_npi_ctl_t *control; /* control buffer (pre-allocated) */
  7601. int ctl_size; /* size of control buffer */
  7602. N_npi_data_t *data; /* data buffer (pre-allocated) */
  7603. int data_size; /* size of data buffer */
  7604. int *get_flags; /* getmsg() flags */
  7605. int expected; /* expected primitive type */
  7606. /* x25getmsg */ {
  7607. int rc = 0; /* return code */
  7608. struct strbuf *get_ctl=NULL; /* getmsg control */
  7609. struct strbuf *get_data=NULL; /* getmsg data */
  7610. int more = 0; /* flag for more data etc */
  7611. int file_status = -1; /* file async status */
  7612. N_npi_ctl_t * result; /* pointer to simplify switch() */
  7613. int packet_type = -1; /* unknown packet thus far */
  7614. #ifdef TRACE
  7615. printf( "TRACE: entering x25getmsg\n" );
  7616. #endif /* TRACE */
  7617. debug( F110, "x25getmsg waiting for packet ", x25prim( expected ), 0);
  7618. /* prepare the control structures for getmsg */
  7619. if (control) {
  7620. if ((get_ctl = (struct strbuf*)malloc(sizeof(struct strbuf))) == NULL)
  7621. {
  7622. perror("kermit x25getmsg(): get_ctl malloc failed\n");
  7623. debug( F100, "x25getmsg malloc failed for get_ctl\n", "", 0);
  7624. return(-1);
  7625. }
  7626. /* allow getmsg to return an unexpected packet type (which may be
  7627. * larger than the expected one)
  7628. */
  7629. get_ctl->maxlen = NPI_MAX_CTL;
  7630. get_ctl->len = 0;
  7631. get_ctl->buf = (char *)control;
  7632. } else {
  7633. printf(
  7634. "kermit x25getmsg(): internal error. control buffer MUST be pre-allocated!\n"
  7635. );
  7636. debug(F100,"x25getmsg internal error. no buffer pre-allocated","",0);
  7637. return( -1 );
  7638. }
  7639. if (data) {
  7640. if ((get_data = (struct strbuf*)malloc(sizeof(struct strbuf))) == NULL)
  7641. {
  7642. perror("kermit x25getmsg(): get_data malloc failed\n");
  7643. debug( F100, "x25getmsg malloc failed for get_data\n", "", 0);
  7644. return(-1);
  7645. }
  7646. get_data->maxlen = (NPI_MAX_DATA < data_size ) ?
  7647. NPI_MAX_DATA :
  7648. data_size;
  7649. get_data->len = 0;
  7650. get_data->buf = (char *)data;
  7651. }
  7652. /* get an X.25 packet -
  7653. * it may be any kind of packet, so check for special cases
  7654. * it may be split into multiple parts - so loop if necessary
  7655. */
  7656. do {
  7657. #ifdef DEBUG
  7658. printf( "kermit: x25getmsg(): getting a message\n" );
  7659. #endif /* DEBUG */
  7660. errno = 0;
  7661. if ((more = getmsg(fd, get_ctl, get_data, get_flags)) < 0) {
  7662. #ifdef DEBUG
  7663. printf( "kermit: x25getmsg(): getmsg returned an error\n" );
  7664. perror( "getmsg error was" );
  7665. #endif /* DEBUG */
  7666. debug(F101, "x25getmsg getmsg returned an error\n", "", errno);
  7667. if ((errno == EAGAIN) && (get_data && (get_data->len > 0)) ) {
  7668. /* was in non-blocking mode, nothing to get, but we're
  7669. * already waiting for the rest of the packet -
  7670. * switch to blocking mode for the next read.
  7671. * file_status used to reset file status before returning
  7672. */
  7673. if ((file_status = fcntl(fd, F_GETFL, 0)) < 0
  7674. || fcntl(fd, F_SETFL, file_status & ~O_NDELAY) < 0)
  7675. {
  7676. perror("x25getmsg(): couldn't change x25 blocking mode");
  7677. debug(F101,
  7678. "x25getmsg fcntl returned an error\n", "", errno);
  7679. /* netclos(); */
  7680. rc = -1;
  7681. break;
  7682. } else {
  7683. /* loop again into a blocking getmsg() */
  7684. continue;
  7685. }
  7686. } else {
  7687. /* no data to get in non-blocking mode - return empty handed */
  7688. perror( "x25getmsg(): getmsg failed" );
  7689. debug(F101,"x25getmsg getmsg returned an error\n", "", errno);
  7690. rc = -1;
  7691. break;
  7692. }
  7693. } else if (more & MORECTL) {
  7694. /* panic - the control information was larger than the
  7695. * maximum control buffer size!
  7696. */
  7697. /* riehm: close connection? */
  7698. #ifdef DEBUG
  7699. printf("x25getmsg(): received partial control packet - panic\n");
  7700. #endif /* DEBUG */
  7701. debug( F101, "x25getmsg getmsg bad control block\n", "", errno);
  7702. rc = -1;
  7703. break;
  7704. }
  7705. if (result = (N_npi_ctl_t *)control) {
  7706. packet_type = result->bind_ack.PRIM_type;
  7707. if (packet_type != N_OK_ACK) {
  7708. x25lastmsg = packet_type;
  7709. }
  7710. }
  7711. #ifdef DEBUG
  7712. /* printf( "kermit: x25getmsg(): getting " ); */
  7713. if (get_ctl->len > 0) {
  7714. x25dump_prim(result);
  7715. }
  7716. debug(F110,
  7717. "x25getmsg got packet ",
  7718. x25prim( result->bind_ack.PRIM_type ),
  7719. 0
  7720. );
  7721. #endif /* DEBUG */
  7722. if (get_ctl->len >= (int)sizeof(result->bind_ack.PRIM_type)) {
  7723. /* not as pretty as a switch(), but switch can't handle
  7724. * runtime variable values :-(
  7725. */
  7726. if (packet_type == expected ) {
  7727. /* got what we wanted, special case for DATA_IND
  7728. * packets though */
  7729. /* riehm: check Q-bit ? */
  7730. #ifdef DEBUG
  7731. printf("x25getmsg(): got expected packet\nrc is %d\n", rc);
  7732. #endif /* DEBUG */
  7733. if (packet_type == N_DATA_IND ) {
  7734. /* data received. May be incomplete, even though
  7735. * getmsg returned OK
  7736. */
  7737. if (result->data_ind.DATA_xfer_flags & N_MORE_DATA_FLAG)
  7738. more |= MOREDATA;
  7739. if (result->data_ind.DATA_xfer_flags & N_RC_FLAG)
  7740. printf( "x25getmsg(): data packet wants ack\n" );
  7741. }
  7742. } else if( packet_type == N_DISCON_IND) {
  7743. printf( "X25 diconnected\n" );
  7744. /* riehm: need to acknowledge a disconnection? */
  7745. x25clear();
  7746. /* x25unbind( ttyfd ); */
  7747. rc = -1;
  7748. } else if( packet_type == N_ERROR_ACK) {
  7749. errno = result->error_ack.UNIX_error;
  7750. perror( "X25 error received" );
  7751. rc = -1;
  7752. } else {
  7753. printf("x25getmsg(): failed %s\n", x25err(packet_type));
  7754. rc = -1;
  7755. }
  7756. }
  7757. #ifdef COMMENT
  7758. else {
  7759. /* Panic - no control data */
  7760. printf( "kermit: x25getmsg(): no control data with packet\n" );
  7761. rc = -1;
  7762. }
  7763. #endif /* COMMENT */
  7764. if (get_data && (get_data->len >= 0)) {
  7765. get_data->buf += get_data->len;
  7766. get_data->maxlen -= get_data->len;
  7767. }
  7768. } while ((rc == 0)
  7769. && (get_data && (get_data->maxlen > 0))
  7770. && (more & MOREDATA)
  7771. );
  7772. /* return the file status to its original value, unless its still
  7773. * set to -1, or one of the fcntl's failed */
  7774. if ((file_status >= 0) && fcntl(fd, F_SETFL, file_status) < 0)
  7775. rc = -1;
  7776. /*
  7777. * Verify that we received an expected primitive
  7778. * there is apparantly an error case where the primitive is set
  7779. * correctly, but there is not enough data in the control structure
  7780. */
  7781. if ((packet_type != expected) && (get_ctl->len >= ctl_size) ) {
  7782. fprintf(stderr,
  7783. "x25getmsg(): %s NOT received. Primitive received was %s\n",
  7784. x25prim( expected ), x25prim( packet_type ));
  7785. debug(F110, "x25getmsg got an unexpected packet ",
  7786. x25prim(packet_type),
  7787. 0
  7788. );
  7789. rc = -1;
  7790. }
  7791. if (rc == 0) {
  7792. if (get_data && ( get_data->len >= 0)) {
  7793. rc = get_data->len;
  7794. }
  7795. }
  7796. if (get_ctl) { free(get_ctl); get_ctl = NULL; }
  7797. if (get_data) { free(get_data); get_data = NULL; }
  7798. #ifdef COMMENT
  7799. #ifdef DEBUG
  7800. printf( "kermit x25getmsg(): returning %d\n", rc );
  7801. #endif /* DEBUG */
  7802. #endif /* COMMENT */
  7803. debug(F110, "x25getmsg returning packet ", x25prim( packet_type ), 0);
  7804. #ifdef TRACE
  7805. printf( "TRACE: leaving x25getmsg\n" );
  7806. #endif /* TRACE */
  7807. return(rc);
  7808. }
  7809. /*****************************************************************************
  7810. * Function: x25putmsg()
  7811. *
  7812. * Description:
  7813. * send a message to a X25 STREAM
  7814. *
  7815. * Parameters:
  7816. * fd - file descriptor to x25 device (opened)
  7817. * control - control buffer (pre-allocated)
  7818. * data - data buffer (pre-allocated)
  7819. * data_len - length of data to be transmitted
  7820. * put_flags - flags for putmsg()
  7821. *
  7822. * Return Value:
  7823. * >= 0 number of bytes transmitted
  7824. * -1 error
  7825. */
  7826. int
  7827. x25putmsg(fd, control, data, data_len, put_flags)
  7828. int fd; /* X25 device (opened) */
  7829. N_npi_ctl_t *control; /* control buffer (pre-allocated) */
  7830. N_npi_data_t *data; /* data buffer (pre-allocated) */
  7831. int data_len; /* length of data (not the size of
  7832. the buffer) */
  7833. int *put_flags; /* putmsg() flags */
  7834. /* x25putmsg */ {
  7835. int rc = 0; /* return code */
  7836. ulong type; /* primitive type */
  7837. struct strbuf *put_ctl = NULL; /* putmsg control */
  7838. struct strbuf *put_data = NULL; /* putmsg data */
  7839. #ifdef TRACE
  7840. printf( "TRACE: entering x25putmsg\n" );
  7841. #endif /* TRACE */
  7842. #ifdef DEBUG
  7843. printf( "kermit: x25putmsg(): putting " );
  7844. x25dump_prim( control );
  7845. printf( "\tdata:\t\t" );
  7846. x25dump_data( data, 0, data_len );
  7847. debug(F110,"x25putmsg: putting packet ",x25prim(control->PRIM_type),0);
  7848. #endif /* DEBUG */
  7849. if (control) {
  7850. put_ctl = (struct strbuf *)malloc( sizeof( struct strbuf ) );
  7851. if (put_ctl == NULL) {
  7852. perror("kermit x25putmsg(): put_ctl malloc failed\n");
  7853. return(-1);
  7854. }
  7855. put_ctl->maxlen = 0; /* unused by putmsg */
  7856. put_ctl->len = NPI_MAX_CTL;
  7857. put_ctl->buf = (char *)control;
  7858. }
  7859. if (data && ( data_len > 0)) {
  7860. put_data = (struct strbuf *)malloc( sizeof( struct strbuf ) );
  7861. if( put_data == NULL) {
  7862. perror("kermit x25putmsg(): put_data malloc failed\n");
  7863. return(-1);
  7864. }
  7865. put_data->maxlen = 0; /* unused by putmsg */
  7866. put_data->len = data_len;
  7867. put_data->buf = (char *)data;
  7868. }
  7869. errno = 0;
  7870. rc = putmsg (fd, put_ctl, put_data, 0);
  7871. if (rc < 0) {
  7872. printf("x25putmsg(): couldn't put %s\n",x25prim(control->PRIM_type));
  7873. perror("kermit: x25putmsg(): putmsg failed");
  7874. return(-1);
  7875. }
  7876. /* riehm: this should perhaps be discounted! */
  7877. x25lastmsg = control->PRIM_type;
  7878. #ifdef COMMENT
  7879. #ifdef DEBUG
  7880. printf( "kermit debug: x25putmsg() returning %d\n", data_len );
  7881. #endif /* DEBUG */
  7882. #endif /* COMMENT */
  7883. debug( F101, "x25putmsg block size put ", "", data_len);
  7884. #ifdef TRACE
  7885. printf( "TRACE: leaving x25putmsg\n" );
  7886. #endif /* TRACE */
  7887. return( data_len );
  7888. }
  7889. /*****************************************************************************
  7890. * Function: x25bind
  7891. * Description: The bind submitted to NPI provides the information required
  7892. * by the packet layer for it to listen for suitable incoming
  7893. * calls.
  7894. *
  7895. * WARNING:
  7896. *
  7897. * This routine needs to be called in a completely different manner for
  7898. * the client and server side. When starting a client, the
  7899. * num_waiting_calls and CUD information should all be set to 0! The
  7900. * client's CUD must be inserted in the CONN_REQ data block.
  7901. * When starting a server, the CUD must be set to a CUD pattern, and
  7902. * the number of waiting calls should be set to a number other than 0.
  7903. * (num waiting calls is the number of incomming calls which are to be
  7904. * put on hold while the server is servicing another client.)
  7905. *
  7906. * Who invented this crap?
  7907. *
  7908. * Parameters:
  7909. * fd - X25 device (opened)
  7910. * addr - local address
  7911. * cud - User Data (null terminated)
  7912. * cud_len - User Data length
  7913. * num_waiting_calls - number of outstanding calls allowed on this stream
  7914. * line - logical port number (1)
  7915. * flags - 0, DEFAULT_LISTENER or TOKEN_REQUEST
  7916. *
  7917. * Return Value:
  7918. * if binding is successful, 0 is returned for a client, and a token is
  7919. * returned for a server
  7920. *
  7921. * Return code: 0 if successful
  7922. * -1 if unsuccessful
  7923. *****************************************************************************/
  7924. ulong
  7925. x25bind(fd, addr, cud, cud_len, num_waiting_calls, line, bind_flags)
  7926. int fd; /* X25 device (opened) */
  7927. char * addr; /* local address */
  7928. char * cud; /* Call User Data (null terminated) */
  7929. int cud_len; /* User Data length */
  7930. int num_waiting_calls; /* Outstanding calls allowed */
  7931. int line; /* logical port number */
  7932. ulong bind_flags; /* 0, DEFAULT_LISTENER or TOKEN_REQUEST */
  7933. /* x25bind */ {
  7934. ulong rc; /* return code */
  7935. int get_flags; /* priority flag passed to getmsg */
  7936. int put_flags = 0; /* output flags for putmsg, always 0 */
  7937. ulong type; /* primitive type */
  7938. N_bind_req_t *bind_req; /* pointer to N_BIND_REQ primitive */
  7939. N_bind_ack_t *bind_ack; /* pointer to N_BIND_ACK primitive */
  7940. char *addtl_info; /* pointer to info in addition to
  7941. * the N_BIND_REQ primitive that is
  7942. * passed in the control structure
  7943. * to putmsg */
  7944. int addr_len = 0; /* length of address string */
  7945. ulong bind_req_t_size; /* for debugging only */
  7946. #ifdef TRACE
  7947. printf("TRACE: entering x25bind\n" );
  7948. #endif /* TRACE */
  7949. #ifdef DEBUG
  7950. printf("TRACE: x25bind( %d, %s, %s, %d, %d )\n",
  7951. fd, addr, cud, line, bind_flags
  7952. );
  7953. #endif /* DEBUG */
  7954. /*
  7955. * Allocate and zero out space to hold the control portion of the
  7956. * message passed to putmsg. This will contain the N_BIND_REQ
  7957. * primitive and any additional info required for that.
  7958. *
  7959. * Note: allocated space is the size of the union typedef
  7960. * N_npi_ctl_t to allow the use fo the generic x25putmsg routine.
  7961. */
  7962. bind_req = (N_bind_req_t *) malloc(sizeof( N_npi_ctl_t));
  7963. if (bind_req == NULL) {
  7964. perror("kermit: x25bind(): bind_req malloc failed");
  7965. debug(F100, "x25bind bind_req malloc failed", "", 0);
  7966. return(-1);
  7967. }
  7968. bzero((char *)bind_req, sizeof(N_npi_ctl_t));
  7969. /* Build the Bind Request Primitive */
  7970. bind_req->PRIM_type = (ulong) N_BIND_REQ;
  7971. /* Note that the address length is n+2 and NOT n. Two bytes MUST preceed
  7972. * the actual address in an N_BIND_REQ. The first byte contains the
  7973. * line number being used with this address, and the second byte is the
  7974. * X.121 address prefix, which must be zero.
  7975. */
  7976. addr_len = strlen(addr);
  7977. bind_req->ADDR_length = (ulong) (addr_len + 2);
  7978. bind_req->ADDR_offset = (ulong)(sizeof(N_bind_req_t));
  7979. bind_req->CONIND_number = (ulong)num_waiting_calls; /* server only */
  7980. bind_req->BIND_flags = (ulong) bind_flags; /* 0 in client */
  7981. bind_req->PROTOID_length = (ulong) cud_len; /* 0 in client */
  7982. if (cud_len == 0) {
  7983. bind_req->PROTOID_offset = (ulong) 0;
  7984. } else {
  7985. /* need to remember the trailing NULL in the address - not
  7986. * counted in the address length
  7987. */
  7988. bind_req->PROTOID_offset
  7989. = (ulong) (sizeof(N_bind_req_t) + bind_req->ADDR_length);
  7990. }
  7991. /*
  7992. * Now fill in the additional information required with this primitive
  7993. * (address and protocol information (Call User Data))
  7994. */
  7995. addtl_info = (char *) ((void *)bind_req + bind_req->ADDR_offset);
  7996. /*
  7997. * The bitwise "&" ensures that the line number is only one byte long
  7998. */
  7999. *addtl_info++ = (char) line & 0xff;
  8000. *addtl_info++ = (char) 0; /* X.121 format */
  8001. bcopy( addr, addtl_info, addr_len ); /* include trailing null */
  8002. addtl_info += addr_len;
  8003. if (cud_len > 0)
  8004. bcopy( cud, addtl_info, cud_len );
  8005. /*
  8006. * Call putmsg() to put the bind request message on the stream
  8007. */
  8008. if (x25putmsg(fd,
  8009. (N_npi_ctl_t*)bind_req,
  8010. (N_npi_data_t *)NULL,
  8011. 0,
  8012. &put_flags
  8013. ) < 0) {
  8014. printf( "kermit: x25bind(): x25putmsg failed\n" );
  8015. return(-1);
  8016. }
  8017. /*
  8018. * Allocate and zero out space for the N_BIND_ACK primitive
  8019. */
  8020. bind_ack = (N_bind_ack_t *) malloc(sizeof(N_npi_ctl_t));
  8021. if (bind_ack == NULL){
  8022. perror("kermit: x25bind(): bind_ack malloc failed");
  8023. return(-1);
  8024. }
  8025. bzero(bind_ack, sizeof(N_npi_ctl_t));
  8026. /*
  8027. * Initialize the control structure and flag variable sent to getmsg
  8028. */
  8029. get_flags=0;
  8030. /* get the ACK for the bind */
  8031. #ifdef DEBUG
  8032. printf( "kermit: x25bind() trying to get a BIND_ACK\n" );
  8033. #endif /* DEBUG */
  8034. rc = (ulong)x25getmsg( fd, (N_npi_ctl_t*)bind_ack,
  8035. (int)sizeof( N_bind_ack_t ), (N_npi_data_t*)NULL, 0, &get_flags,
  8036. N_BIND_ACK );
  8037. /* turn quantitive return code into a qualitative one */
  8038. if (rc > 0) rc = 0;
  8039. /* if all went well, get the token from the acknowledgement packet */
  8040. if ((bind_flags & TOKEN_REQUEST ) && ( rc >= 0)) {
  8041. rc = bind_ack->TOKEN_value;
  8042. }
  8043. /* free up the memory we allocated earlier */
  8044. free(bind_req);
  8045. free(bind_ack);
  8046. #ifdef TRACE
  8047. printf( "TRACE: leaving x25bind\n" );
  8048. #endif /* TRACE */
  8049. return( rc );
  8050. }
  8051. /*****************************************************************************
  8052. * Function: x25call
  8053. * Description: This routine builds and sends an N_CONN_REQ primitive, then
  8054. * checks for an N_CONN_CON primitive in return.
  8055. *
  8056. * Parameters:
  8057. * fd - file descriptor of stream
  8058. * caddr - called address (remote address)
  8059. *
  8060. * Functions Referenced:
  8061. * malloc()
  8062. * bzero()
  8063. * getmsg()
  8064. * putmsg()
  8065. *
  8066. * Return code:
  8067. * 0 - if successful
  8068. * -1 if not successful
  8069. *****************************************************************************/
  8070. int
  8071. x25call(fd, remote_nua, cud)
  8072. int fd; /* X25 device (opened) */
  8073. char * remote_nua; /* remote address to call */
  8074. char * cud; /* call user data */
  8075. /* x25call */ {
  8076. int rc; /* return code */
  8077. int flags; /* Connection flags */
  8078. int get_flags; /* priority flags for getmsg */
  8079. ulong type; /* primitive type */
  8080. N_conn_req_t *connreq_ctl; /* pointer to N_CONN_REQ primitive */
  8081. N_npi_data_t *connreq_data; /* pointer to N_CONN_REQ data (CUD) */
  8082. int connreq_data_len; /* length of filled data buffer */
  8083. N_conn_con_t *conncon_ctl; /* pointer to N_CONN_CON primitive */
  8084. N_npi_data_t *conncon_data; /* pointer to any data associated with
  8085. * the N_CONN_CON primitive */
  8086. char *addtl_info; /* pointer to additional info needed
  8087. * for N_CONN_REQ primitive */
  8088. int addr_len; /* length of address */
  8089. #ifdef TRACE
  8090. printf( "TRACE: entering x25call\n" );
  8091. #endif /* TRACE */
  8092. #ifdef DEBUG
  8093. printf( "x25call( %d, %s )\n", fd, remote_nua );
  8094. printf( "connecting to %s on fd %d\n", remote_nua, fd );
  8095. #endif /* DEBUG */
  8096. /*
  8097. * Allocate and zero out space for the N_CONN_REQ primitive
  8098. * use the size of the generic NPI primitive control buffer
  8099. */
  8100. connreq_ctl = (N_conn_req_t *) malloc(sizeof(N_npi_ctl_t));
  8101. if (connreq_ctl == NULL){
  8102. perror("kermit: x25call(): connreq_ctl malloc failed");
  8103. return(-1);
  8104. }
  8105. bzero(connreq_ctl,sizeof(N_npi_ctl_t));
  8106. /*
  8107. * Build the Connection Request Primitive
  8108. */
  8109. flags = 0;
  8110. connreq_ctl->PRIM_type = (ulong) N_CONN_REQ;
  8111. /* Note that the address length is nchai+1 and not n+2. The line number
  8112. * is only passed with the address for the bind. The first byte of
  8113. * the address for the N_CONN primitives contains the X.121
  8114. * address prefix, which must be zero. The remaining bytes are the
  8115. * address itself.
  8116. */
  8117. addr_len = strlen( remote_nua );
  8118. connreq_ctl->DEST_length = (ulong) (addr_len + 1);
  8119. connreq_ctl->DEST_offset = (ulong) sizeof(N_conn_req_t);
  8120. /* connreq_ctl->CONN_flags = (ulong)EX_DATA_OPT | REC_CONF_OPT; */
  8121. connreq_ctl->CONN_flags = (ulong) 0;
  8122. connreq_ctl->QOS_length = (ulong) 0; /* unsupported in AIX 4.1 */
  8123. connreq_ctl->QOS_offset = (ulong) 0; /* unsupported in AIX 4.1 */
  8124. addtl_info = (char *) ((void*)connreq_ctl + connreq_ctl->DEST_offset);
  8125. *addtl_info++ = (char) 0; /* X.121 format */
  8126. bcopy( remote_nua, addtl_info, addr_len );
  8127. /*
  8128. * setup the data buffer for the connection request
  8129. */
  8130. connreq_data = (N_npi_data_t *) malloc(sizeof(N_npi_data_t));
  8131. if (connreq_data == NULL){
  8132. perror("kermit: x25call(): connreq_data malloc failed");
  8133. return(-1);
  8134. }
  8135. bzero(connreq_data,sizeof(N_npi_data_t));
  8136. /* facility selection needs to be put in the front of connreq_data */
  8137. connreq_data_len = 0;
  8138. connreq_data_len += x25facilities( (char *)connreq_data );
  8139. if (cud && *cud) {
  8140. bcopy(cud,
  8141. (char *)((char *)connreq_data + connreq_data_len),
  8142. strlen(cud)
  8143. );
  8144. connreq_data_len += strlen( cud );
  8145. }
  8146. /*
  8147. * Call putmsg() to put the connection request message on the stream
  8148. */
  8149. rc = x25putmsg( fd, (N_npi_ctl_t*)connreq_ctl, connreq_data,
  8150. connreq_data_len, &flags );
  8151. if (rc < 0) {
  8152. return(-1);
  8153. }
  8154. /*
  8155. * Allocate and zero out space for the N_CONN_CON primitive
  8156. */
  8157. if ((conncon_ctl = (N_conn_con_t *) malloc(sizeof(N_npi_ctl_t))) == NULL) {
  8158. perror("kermit: x25call(): conncon_ctl malloc failed");
  8159. return(-1);
  8160. }
  8161. bzero(conncon_ctl, sizeof(N_npi_ctl_t));
  8162. /*
  8163. * Allocate and zero out space for any data associated with N_CONN_CON
  8164. */
  8165. if ( (conncon_data = (N_npi_data_t *) malloc(NPI_MAX_DATA)) == NULL) {
  8166. perror("kermit: x25call(): conncon_data malloc failed");
  8167. return(-1);
  8168. }
  8169. bzero(conncon_data, NPI_MAX_DATA);
  8170. /* Initialize and build the structures for getmsg */
  8171. get_flags=0;
  8172. rc = x25getmsg( fd, (N_npi_ctl_t*)conncon_ctl, (int)sizeof( N_conn_con_t ),
  8173. conncon_data, NPI_MAX_DATA, &get_flags, N_CONN_CON );
  8174. /* turn quantitive return code into a qualitative one */
  8175. if (rc > 0) rc = 0;
  8176. /* Free the space that we no longer need */
  8177. if (connreq_ctl) { free(connreq_ctl); connreq_ctl = NULL; }
  8178. if (conncon_ctl) { free(conncon_ctl); conncon_ctl = NULL; }
  8179. if (conncon_data) { free(conncon_data); conncon_data = NULL; }
  8180. #ifdef TRACE
  8181. printf( "TRACE: leaving x25call\n" );
  8182. #endif /* TRACE */
  8183. return(rc);
  8184. }
  8185. /*****************************************************************************
  8186. * Function: x25getcall
  8187. *
  8188. * Description: This routine checks for an incomming call, verified
  8189. * that it is a CONNIND (connection indication) message, and then
  8190. * accepts the call and returns the file descriptor of the new stream
  8191. *
  8192. * Parameters:
  8193. * fd - file descriptor of listening stream
  8194. *
  8195. * Return Codes:
  8196. * callfd - file descriptor of connected incomming call.
  8197. * - set to -1 if an error occured
  8198. *
  8199. *****************************************************************************/
  8200. int
  8201. x25getcall(fd) int fd; {
  8202. int x25callfd; /* fd of incomming call */
  8203. N_conn_ind_t *connind_ctl; /* connind controll buffer */
  8204. N_npi_data_t *connind_data; /* connind data buffer */
  8205. int get_flags; /* flags for getmsg */
  8206. ulong flags; /* connection flags */
  8207. int rc; /* return code */
  8208. extern x25addr_t remote_nua; /* remote X.25 addr global var */
  8209. #ifdef TRACE
  8210. printf( "TRACE: entering x25getcall\n" );
  8211. #endif /* TRACE */
  8212. /* allocate space for connection indication buffers */
  8213. if ((connind_ctl = (N_conn_ind_t *)malloc(sizeof(N_npi_ctl_t))) == NULL) {
  8214. perror("kermit: x25getcall(): connind_ctl malloc failed");
  8215. return (-1);
  8216. }
  8217. bzero(connind_ctl, sizeof(N_npi_ctl_t));
  8218. if ((connind_data = (N_npi_data_t *)malloc(NPI_MAX_DATA)) == NULL) {
  8219. perror("kermit: x25getcall(): connind_data malloc failed");
  8220. return (-1);
  8221. }
  8222. bzero(connind_data, NPI_MAX_DATA);
  8223. /* initialise control structures */
  8224. get_flags = 0;
  8225. /* call getmsg to check for a connection indication */
  8226. if (x25getmsg(fd,
  8227. (N_npi_ctl_t*)connind_ctl,
  8228. (int)sizeof(N_conn_ind_t),
  8229. connind_data,
  8230. NPI_MAX_DATA,
  8231. &get_flags,
  8232. N_CONN_IND
  8233. ) < 0) {
  8234. #ifdef DEBUG
  8235. printf( "x25getcall(): errno is: %d\n", errno );
  8236. #endif /* DEBUG */
  8237. perror ("x25getcall(): getmsg failed");
  8238. return(-1);
  8239. }
  8240. /* a connection indication was received
  8241. * - pull it to bits and answer the call
  8242. */
  8243. x25seqno = connind_ctl->SEQ_number;
  8244. flags = connind_ctl->CONN_flags;
  8245. #ifdef DEBUG
  8246. printf( "setting remote_nua to a new value due to incomming call\n" );
  8247. #endif /* DEBUG */
  8248. /*
  8249. * no guarantee that the address is null terminated, ensure that
  8250. * after copying that it is (assumption: remote_nua is longer than
  8251. * the address + 1)
  8252. */
  8253. bzero(remote_nua, sizeof(remote_nua));
  8254. /* note: connind_ctl contains a x121 address, which has a null as
  8255. * the FIRST character - strip it off!
  8256. */
  8257. ckstrncpy(remote_nua,
  8258. (char*)((char*)connind_ctl + connind_ctl->SRC_offset + 1),
  8259. connind_ctl->SRC_length - 1
  8260. );
  8261. #ifdef DEBUG
  8262. printf( "remote_nua set to new value of %s\n", remote_nua );
  8263. #endif /* DEBUG */
  8264. /* errors handled by callee */
  8265. x25callfd = x25accept(x25seqno, flags);
  8266. /* free the malloc'd buffers */
  8267. if (connind_ctl) { free(connind_ctl); connind_ctl = NULL; }
  8268. if (connind_data) { free(connind_data); connind_data = NULL; }
  8269. #ifdef TRACE
  8270. printf( "TRACE: leaving x25getcall\n" );
  8271. #endif /* TRACE */
  8272. /* return the file descriptor (or error if < 0) */
  8273. return( x25callfd );
  8274. }
  8275. /*****************************************************************************
  8276. * Function: x25accept
  8277. *
  8278. * Description: accept an incomming call
  8279. * This essentially means opening a new STREAM and sending
  8280. * an acknowledge back to the caller.
  8281. *
  8282. * Parameters:
  8283. * seqno - sequence number for acknowledgement
  8284. * flags - flags passed to us by the caller
  8285. *
  8286. * Return Codes:
  8287. * fd - file descriptor of new STREAM
  8288. * set to -1 if an error occured
  8289. *
  8290. *****************************************************************************/
  8291. int
  8292. x25accept(seqno,flags)
  8293. ulong seqno; /* connection sequence number */
  8294. ulong flags; /* connection flags */
  8295. /* x25accept */ {
  8296. int x25callfd; /* fd for incomming call */
  8297. int get_flags; /* priority flags for getmsg */
  8298. int put_flags = 0; /* flags for putmsg, always 0 */
  8299. int addr_len; /* length of local address */
  8300. ulong token; /* connection token */
  8301. N_conn_res_t *conn_res; /* N_CONN_RES primitive */
  8302. N_ok_ack_t *ok_ack; /* N_OK_ACK primitive */
  8303. char *addtl_info; /* temp pointer */
  8304. int rc; /* temporary return code */
  8305. /* global variables from ckcmai.c */
  8306. extern int revcall, closgr, cudata;
  8307. extern char udata[];
  8308. extern x25addr_t local_nua; /* local X.25 address */
  8309. extern char x25name[]; /* x25 device name (sx25a0) */
  8310. extern char x25dev[]; /* x25 device file /dev/x25pkt */
  8311. extern int x25port; /* logical port to use */
  8312. ulong bind_flags = 0; /* flags for binding the X25 stream */
  8313. #ifdef TRACE
  8314. printf( "TRACE: entering x25accept\n" );
  8315. #endif /* TRACE */
  8316. /* open a new packet level stream */
  8317. if ((x25callfd = open(x25dev, O_RDWR)) < 0) {
  8318. perror ("kermit: x25accept(): X.25 device open error");
  8319. debug(F101,"x25accept() device open error","",errno);
  8320. return(-1);
  8321. }
  8322. /* push the NPI onto the STREAM */
  8323. if (ioctl(x25callfd,I_PUSH,"npi") < 0) {
  8324. perror( "kermit: x25accept(): couldn't push npi on the X25 stream" );
  8325. debug(F101,"x25accept can't push npi on the X25 stream","",errno);
  8326. return (-1);
  8327. }
  8328. /* bind kermit server to the local X25 address */
  8329. /* taken from /usr/samples/sx25/npi/npiserver.c (AIX 4) */
  8330. bind_flags |= TOKEN_REQUEST;
  8331. token = x25bind(x25callfd,local_nua,(char *)NULL,0,0,x25port,bind_flags);
  8332. if (token < 0) {
  8333. printf( "kermit: x25accept(): couldn't bind to local X25 address\n" );
  8334. netclos();
  8335. return(-1);
  8336. }
  8337. /* allocate connection response primitive */
  8338. if ((conn_res = (N_conn_res_t *)malloc( NPI_MAX_CTL )) == NULL) {
  8339. perror("kermit: x25accept(): conn_res malloc failed");
  8340. return (-1);
  8341. }
  8342. bzero((char *)conn_res, NPI_MAX_CTL);
  8343. /* setup connection response primitive */
  8344. addr_len = strlen( local_nua );
  8345. conn_res->PRIM_type = (ulong)N_CONN_RES;
  8346. conn_res->TOKEN_value = token;
  8347. /* note address length is n+1 to accomodate the X.121 address prefix */
  8348. conn_res->RES_length = (ulong)(addr_len + 1);
  8349. conn_res->RES_offset = (ulong)sizeof( N_conn_res_t );
  8350. conn_res->SEQ_number = seqno;
  8351. conn_res->CONN_flags = 0;
  8352. conn_res->QOS_length = 0; /* unsupported - must be 0 (!?) */
  8353. conn_res->QOS_offset = 0;
  8354. addtl_info = (char *)((char *)conn_res + conn_res->RES_offset);
  8355. *addtl_info++ = (char)0; /* X.121 address prefix */
  8356. bcopy( local_nua, addtl_info, addr_len );
  8357. /*
  8358. * send off the connect response
  8359. */
  8360. if (x25putmsg(x25callfd,
  8361. (N_npi_ctl_t*)conn_res,
  8362. (N_npi_data_t *)NULL,
  8363. 0,
  8364. &put_flags
  8365. ) < 0 ) {
  8366. perror("kermit: x25accept(): putmsg connect response failed");
  8367. return(-1);
  8368. }
  8369. /*
  8370. * Allocate and zero out space for the OK_ACK primitive
  8371. */
  8372. if ((ok_ack = (N_ok_ack_t *) malloc(sizeof(N_npi_ctl_t))) == NULL) {
  8373. perror("kermit: x25call(): ok_ack malloc failed");
  8374. return(-1);
  8375. }
  8376. bzero(ok_ack, sizeof(N_npi_ctl_t));
  8377. /* Initialize and build the structures for getmsg */
  8378. get_flags=0;
  8379. rc = (int)x25getmsg(x25callfd,
  8380. (N_npi_ctl_t*)ok_ack,
  8381. (int)sizeof(N_ok_ack_t),
  8382. (N_npi_data_t*)NULL,
  8383. 0,
  8384. &get_flags,
  8385. N_OK_ACK
  8386. );
  8387. if (rc == 0) {
  8388. /* sequence number is only for disconnecting when not connected !? */
  8389. x25seqno = 0;
  8390. }
  8391. /* free up malloc'ed buffer space */
  8392. if (conn_res) { free(conn_res); conn_res = NULL; }
  8393. if (ok_ack) { free(ok_ack); ok_ack = NULL; }
  8394. #ifdef TRACE
  8395. printf( "TRACE: leaving x25accept\n" );
  8396. #endif /* TRACE */
  8397. return( ( rc >= 0 ) ? x25callfd : -1 );
  8398. }
  8399. /*****************************************************************************
  8400. * Function: x25unbind
  8401. *
  8402. * Description: This subroutine builds and sends an unbind request and gets
  8403. * the acknowledgement for it.
  8404. *
  8405. * Parameters:
  8406. * fd - File descriptor of the stream
  8407. *
  8408. * Functions Referenced:
  8409. * getmsg()
  8410. * putmsg()
  8411. * malloc()
  8412. * bzero()
  8413. *
  8414. * Return code:
  8415. * 0 - if successful
  8416. * -1 - if not successful
  8417. *****************************************************************************/
  8418. int
  8419. x25unbind(fd) int fd; { /* X25 device (opened) */
  8420. int rc; /* return code */
  8421. int flags; /* bind flags */
  8422. int get_flags; /* priority flag for getmsg */
  8423. ulong type; /* primitive type */
  8424. N_unbind_req_t *unbind_req; /* pointer to N_UNBIND_REQ */
  8425. N_ok_ack_t *ok_ack; /* pointer to N_OK_ACK */
  8426. #ifdef TRACE
  8427. printf( "TRACE: entering x25unbind\n" );
  8428. #endif /* TRACE */
  8429. #ifdef DEBUG
  8430. /* printf( "x25unbind( %d )\n", fd ); */
  8431. #endif /* DEBUG */
  8432. debug(F101,"x25unbind closing x25 connection #","",fd);
  8433. /* Allocate and zero out space to hold the N_UNBIND_REQ primitive */
  8434. unbind_req = (N_unbind_req_t *) malloc(sizeof(N_npi_ctl_t));
  8435. if (unbind_req == NULL) {
  8436. perror("kermit: x25unbind(): unbind_req malloc failed");
  8437. return(-1);
  8438. }
  8439. bzero(unbind_req, sizeof(N_npi_ctl_t));
  8440. /*
  8441. * Build the Unbind Request Primitive
  8442. */
  8443. flags = 0;
  8444. unbind_req->PRIM_type = (ulong) N_UNBIND_REQ;
  8445. /*
  8446. * Call putmsg() to put the bind request message on the stream
  8447. */
  8448. if (x25putmsg(fd,
  8449. (N_npi_ctl_t*)unbind_req,
  8450. (N_npi_data_t *)NULL,
  8451. 0,
  8452. &flags
  8453. ) < 0) {
  8454. perror ("kermit: x25unbind(): putmsg failed");
  8455. return(-1);
  8456. }
  8457. /* Allocate and Zero out space for the N_OK_ACK primitive */
  8458. ok_ack = (N_ok_ack_t *) malloc(sizeof(N_npi_ctl_t));
  8459. if (ok_ack == NULL) {
  8460. perror("kermit x25unbind(): ok_ack malloc failed\n");
  8461. return(-1);
  8462. }
  8463. bzero(ok_ack, sizeof(N_npi_ctl_t));
  8464. /* Initialize and build the control structure for getmsg */
  8465. get_flags=0;
  8466. /* Call getmsg() to check for an acknowledgement */
  8467. rc = x25getmsg(fd,
  8468. (N_npi_ctl_t*)ok_ack,
  8469. (int)sizeof(N_ok_ack_t),
  8470. (N_npi_data_t*)NULL,
  8471. 0,
  8472. &get_flags,
  8473. N_OK_ACK
  8474. );
  8475. if (rc < 0) {
  8476. perror ("kermit: x25unbind: getmsg failed");
  8477. return(-1);
  8478. }
  8479. /* Free up the space that we no longer need */
  8480. if (unbind_req) { free(unbind_req); unbind_req = NULL; }
  8481. if (ok_ack) { free(ok_ack); ok_ack = NULL; }
  8482. #ifdef TRACE
  8483. printf( "TRACE: leaving x25unbind\n" );
  8484. #endif /* TRACE */
  8485. return(0);
  8486. }
  8487. /*****************************************************************************
  8488. * Function: x25xin
  8489. *
  8490. * Description:
  8491. * Read n characters from X.25 circuit into buf (AIX only)
  8492. *
  8493. * Parameters:
  8494. * data_buf_len maximum size of data buffer
  8495. * data_buf pointer to pre-allocated buffer space
  8496. *
  8497. * Return Value:
  8498. * the number of characters actually read
  8499. */
  8500. int
  8501. x25xin(data_buf_len,data_buf) int data_buf_len; CHAR *data_buf; {
  8502. struct strbuf getmsg_ctl; /* streams control structure */
  8503. struct strbuf getmsg_data; /* streams data structure */
  8504. int rc = 0; /* return code */
  8505. int getmsg_flags; /* packet priority flags */
  8506. char * ctl_buf; /* npi control buffer */
  8507. N_npi_ctl_t * result; /* pointer to simplify switch() */
  8508. #ifdef TRACE
  8509. printf( "TRACE: entering x25xin\n" );
  8510. #endif /* TRACE */
  8511. /* ensure that no maximum's are overridden */
  8512. data_buf_len = (NPI_MAX_DATA < data_buf_len) ? NPI_MAX_DATA : data_buf_len;
  8513. /* allocate space for packet control info */
  8514. if ((ctl_buf = (char *)malloc(NPI_MAX_CTL)) == NULL) {
  8515. perror( "kermit: x25xin(): ctl_buf malloc" );
  8516. return(-1);
  8517. }
  8518. #ifdef COMMENT
  8519. /* riehm: need zeroed buffer for getmsg? */
  8520. bzero( ctl_buf, NPI_MAX_CTL );
  8521. /* clear data buffer */
  8522. bzero( data_buf, data_buf_len );
  8523. #endif /* COMMENT */
  8524. getmsg_flags = 0; /* get the first packet available */
  8525. rc = x25getmsg(ttyfd,
  8526. ctl_buf,
  8527. NPI_MAX_CTL,
  8528. data_buf,
  8529. data_buf_len,
  8530. &getmsg_flags,
  8531. N_DATA_IND
  8532. );
  8533. #ifdef COMMENT
  8534. #ifdef DEBUG
  8535. if (rc >= 0) {
  8536. printf( "kermit: x25xin(): got " );
  8537. x25dump_data( data_buf, 0, rc );
  8538. } else {
  8539. printf( "x25xin(): attempt to get data resulted in an error\n" );
  8540. }
  8541. #endif /* DEBUG */
  8542. #endif /* COMMENT */
  8543. /* free buffers */
  8544. if (ctl_buf) { free(ctl_buf); ctl_buf = NULL; }
  8545. #ifdef TRACE
  8546. printf( "TRACE: leaving x25xi\n" );
  8547. #endif /* TRACE */
  8548. return(rc);
  8549. }
  8550. /*****************************************************************************
  8551. * Function: x25write
  8552. *
  8553. * Description:
  8554. * write a block of characters to the X25 STREAM (AIX)
  8555. *
  8556. * Parameters:
  8557. * fd file descriptor to write to
  8558. * databuf buffer containing data to write
  8559. * databufsize size of the buffer to write
  8560. *
  8561. * Return Value:
  8562. * size the number of bytes actually transmitted
  8563. */
  8564. int
  8565. x25write(fd, databuf, databufsize)
  8566. int fd; /* X25 STREAMS file descriptor (ttyfd) */
  8567. char *databuf; /* buffer to write */
  8568. int databufsize; /* buffer size */
  8569. /* x25write */ {
  8570. N_data_req_t *data_req_ctl;
  8571. int rc; /* return code (size transmitted) */
  8572. int write_flags = 0; /* always 0 !? */
  8573. #ifdef TRACE
  8574. printf( "TRACE: entering x25write\n" );
  8575. #endif /* TRACE */
  8576. if ((data_req_ctl = (N_data_req_t *)malloc(NPI_MAX_CTL) ) == NULL) {
  8577. perror( "kermit: x25write(): data_req_ctl malloc" );
  8578. return(-1);
  8579. }
  8580. data_req_ctl->PRIM_type = N_DATA_REQ;
  8581. data_req_ctl->DATA_xfer_flags = 0;
  8582. /* riehm: possible extension
  8583. * possibly need to think about splitting up the data buffer
  8584. * into multiple parts if databufsize > NPI_MAX_DATA
  8585. */
  8586. #ifdef COMMENT
  8587. #ifdef DEBUG
  8588. printf( "kermit: x25write(): writing data to x25 stream\n" );
  8589. printf( "\tdata:\t" );
  8590. x25dump_data(databuf, 0, databufsize);
  8591. #endif /* DEBUG */
  8592. #endif /* COMMENT */
  8593. rc = x25putmsg(fd,
  8594. (N_npi_ctl_t*)data_req_ctl,
  8595. (N_npi_data_t*)databuf,
  8596. databufsize,
  8597. &write_flags
  8598. );
  8599. if (data_req) { free(data_req_ctl); data_req = NULL; }
  8600. #ifdef TRACE
  8601. printf( "TRACE: leaving x25write\n" );
  8602. #endif /* TRACE */
  8603. return(rc);
  8604. }
  8605. /*****************************************************************************
  8606. * Function: x25local_nua
  8607. *
  8608. * Description:
  8609. * This routine is only interesting for IBM computers. In order
  8610. * to set up a connection (see x25bind()) you need to know the
  8611. * local NUA (x25 address). Unfortunately, you need all this code
  8612. * to find that out, I just hope this works for everyone else!
  8613. *
  8614. * Parameters:
  8615. * a pre-allocated character buffer, long enough to hold an X.25 address
  8616. * and the tailing null.
  8617. *
  8618. * Return Value:
  8619. * the length of the address string.
  8620. * 0 = error
  8621. */
  8622. int
  8623. x25local_nua(char *buf) {
  8624. struct CuAt *response; /* structure to fill with info from ODM */
  8625. CLASS_SYMBOL retClass; /* ODM class */
  8626. char query[64]; /* odm database query */
  8627. int rc = 0; /* return value (length of local NUA) */
  8628. extern char x25name[]; /* x25 device name (sx25a0) */
  8629. #ifdef TRACE
  8630. printf( "TRACE: entering x25local_nua\n" );
  8631. #endif /* TRACE */
  8632. /* set up query string */
  8633. if (x25name[0] == '\0') {
  8634. #ifdef DEBUG
  8635. printf( "kermit: x25local_nua(): No x25 device set, trying sx25a0\n" );
  8636. #endif /* DEBUG */
  8637. strcpy( x25name, "sx25a0" );
  8638. }
  8639. ckmakmsg(query, sizeof(query), "name like ",x25name,
  8640. " and attribute like local_nua");
  8641. /* initialise ODM database */
  8642. odmerrno = 0;
  8643. if (odm_initialize() == -1) {
  8644. printf( "x25local_nua(): can't initialize ODM database");
  8645. switch (odmerrno) {
  8646. case ODMI_INVALID_PATH:
  8647. printf( "invalid path\n" );
  8648. break;
  8649. case ODMI_MALLOC_ERR:
  8650. printf( "malloc failed\n" );
  8651. break;
  8652. default:
  8653. printf( "unknown error %d\nPlease call IBM\n", odmerrno );
  8654. }
  8655. return(rc);
  8656. }
  8657. /* open the CuAt class */
  8658. retClass = odm_open_class(CuAt_CLASS);
  8659. if (((int)retClass) == -1) {
  8660. printf( "kermit: x25local_nua(): can't open CuAt class in odm. " );
  8661. switch (odmerrno) {
  8662. case ODMI_CLASS_DNE:
  8663. printf( "CuAt class doesn't exist\n" );
  8664. break;
  8665. case ODMI_CLASS_PERMS:
  8666. printf( "permission to CuAt class file denied\n" );
  8667. break;
  8668. case ODMI_MAGICNO_ERR:
  8669. printf( "CuAt is an invalid ODM object class\n" );
  8670. break;
  8671. case ODMI_OPEN_ERR:
  8672. printf( "cannot open CuAt class - and don't know why!\n" );
  8673. break;
  8674. case ODMI_INVALID_PATH:
  8675. printf( "invalid path\n" );
  8676. break;
  8677. case ODMI_TOOMANYCLASSES:
  8678. printf( "too many object classes have been opened\n" );
  8679. break;
  8680. default:
  8681. printf( "unknown error %d\nPlease call IBM\n", odmerrno );
  8682. }
  8683. return(rc);
  8684. }
  8685. #ifdef DEBUG
  8686. printf("retClass= %d\n", retClass);
  8687. #endif /* DEBUG */
  8688. response = (struct CuAt *)odm_get_first( retClass, query, NULL );
  8689. if (((int)response) == -1) {
  8690. printf( "kermit: x25local_nua(): odm query failed " );
  8691. switch (odmerrno) {
  8692. case ODMI_BAD_CRIT: /* Programming error */
  8693. printf( "bad search criteria\n" );
  8694. break;
  8695. case ODMI_CLASS_DNE:
  8696. printf( "CuAt class doesn't exist\n" );
  8697. break;
  8698. case ODMI_CLASS_PERMS:
  8699. printf( "permission to CuAt class file denied\n" );
  8700. break;
  8701. case ODMI_INTERNAL_ERR:
  8702. printf("odm internal error\nPlease contact your administrator\n" );
  8703. break;
  8704. case ODMI_INVALID_CLXN:
  8705. printf("CuAt is invalid or inconsistent odm class collection\n");
  8706. break;
  8707. case ODMI_INVALID_PATH:
  8708. printf( "invalid path\n" );
  8709. break;
  8710. case ODMI_MAGICNO_ERR:
  8711. printf( "CuAt is an invalid ODM object class\n" );
  8712. break;
  8713. case ODMI_MALLOC_ERR:
  8714. printf( "malloc failed\n" );
  8715. break;
  8716. case ODMI_OPEN_ERR:
  8717. printf( "cannot open CuAt class - and don't know why!\n" );
  8718. break;
  8719. case ODMI_TOOMANYCLASSES:
  8720. printf( "too many object classes have been opened\n" );
  8721. break;
  8722. default:
  8723. printf( "unknown error %d\nPlease call IBM\n", odmerrno );
  8724. }
  8725. return(rc);
  8726. }
  8727. /* check for a meaningfull response */
  8728. if (response != NULL) {
  8729. if (response->value != NULL) {
  8730. strcpy(buf, response->value);
  8731. rc = strlen( buf );
  8732. #ifdef DEBUG
  8733. /*
  8734. printf( "attribute name is: %s\n", (char *)response->attribute );
  8735. printf( "I think my address is %s\n", (char*)response->value );
  8736. */
  8737. #endif /* DEBUG */
  8738. } else {
  8739. printf( "kermit: x25local_nua(): couldn't find the local NUA\n" );
  8740. }
  8741. } else {
  8742. switch (odmerrno) {
  8743. case ODMI_BAD_CRIT:
  8744. printf( "Error: ODMI_BAD_CRIT - bad criteria\n" );
  8745. break;
  8746. case ODMI_CLASS_DNE:
  8747. printf( "Error: ODMI_CLASS_DNE - class doesn't exist\n" );
  8748. break;
  8749. case ODMI_CLASS_PERMS:
  8750. printf( "Error: ODMI_CLASS_PERMS - class permissions\n" );
  8751. break;
  8752. case ODMI_INTERNAL_ERR:
  8753. printf( "Error: ODMI_INTERNAL_ERR - panic\n" );
  8754. break;
  8755. case ODMI_INVALID_CLXN:
  8756. printf( "Error: ODMI_INVALID_CLXN - invalid collection\n" );
  8757. break;
  8758. case ODMI_INVALID_PATH:
  8759. printf( "Error: ODMI_INVALID_PATH - invalid path - what path?\n" );
  8760. break;
  8761. case ODMI_MAGICNO_ERR:
  8762. printf( "Error: ODMI_MAGICNO_ERR - invalid object magic\n" );
  8763. break;
  8764. case ODMI_MALLOC_ERR:
  8765. printf( "Error: ODMI_MALLOC_ERR - malloc failed\n" );
  8766. break;
  8767. case ODMI_OPEN_ERR:
  8768. printf( "Error: ODMI_OPEN_ERR - cannot open class\n" );
  8769. break;
  8770. case ODMI_TOOMANYCLASSES:
  8771. printf( "Error: ODMI_TOOMANYCLASSES - too many classes\n" );
  8772. break;
  8773. default:
  8774. printf( "Unknown error!\n" );
  8775. }
  8776. return(rc);
  8777. }
  8778. /* close the database again */
  8779. odm_close_class( retClass );
  8780. /* forget about ODM all together */
  8781. odm_terminate();
  8782. #ifdef TRACE
  8783. printf( "TRACE: leaving x25local_nua\n" );
  8784. #endif /* TRACE */
  8785. debug(F110, "x25local_nua local address is ", buf, 0);
  8786. return(rc);
  8787. }
  8788. /*****************************************************************************
  8789. * Function: x25facilities
  8790. *
  8791. * Description:
  8792. * build up the facilities data packet for a connection request
  8793. *
  8794. * Parameters:
  8795. * a pre-allocated char buffer, normally NPI_MAX_DATA big.
  8796. *
  8797. * Return Value:
  8798. * the number of characters inserted into the buffer
  8799. */
  8800. int
  8801. x25facilities(buffer) char *buffer; {
  8802. extern int revcall;
  8803. extern int closgr;
  8804. char *p; /* temp pointer */
  8805. char *start; /* temp pointer */
  8806. #ifdef TRACE
  8807. printf( "TRACE: entering x25facilities\n" );
  8808. #endif /* TRACE */
  8809. p = buffer + 1;
  8810. start = p;
  8811. #ifdef DEBUG
  8812. printf( "kermit: x25facilities(): getting X25 facilities\n" );
  8813. #endif /* DEBUG */
  8814. if (revcall != 0) {
  8815. #ifdef DEBUG
  8816. printf("reverse charge: %d\n", revcall );
  8817. #endif /* DEBUG */
  8818. *++p = 0x01;
  8819. *++p = revcall;
  8820. }
  8821. if (closgr > 0) {
  8822. #ifdef DEBUG
  8823. printf("closed user group: %d\n", closgr );
  8824. #endif /* DEBUG */
  8825. *++p = 0x03;
  8826. *++p = closgr;
  8827. }
  8828. #ifdef DEBUG
  8829. if (p == start) {
  8830. printf( "no facilities\n" );
  8831. }
  8832. #endif /* DEBUG */
  8833. /* set the size of the facilities buffer */
  8834. *buffer = (char)( p - start ) & 0xff;
  8835. #ifdef DEBUG
  8836. printf( "kermit: x25facilities(): returning %d\n", (int)(p - buffer) );
  8837. #endif /* DEBUG */
  8838. #ifdef TRACE
  8839. printf( "TRACE: leaving x25facilities\n" );
  8840. #endif /* TRACE */
  8841. /* return the size of the facilities with size byte */
  8842. /* 1 == no facilities, 0 byte returned as facilities size */
  8843. return( (int)(p - buffer) );
  8844. }
  8845. /*
  8846. * reset the connection
  8847. */
  8848. int
  8849. x25reset(cause, diagn) char cause; char diagn; {
  8850. /* not implemented */
  8851. #ifdef TRACE
  8852. printf( "TRACE: entering x25reset\n" );
  8853. #endif /* TRACE */
  8854. #ifdef TRACE
  8855. printf( "TRACE: leaving x25reset\n" );
  8856. #endif /* TRACE */
  8857. return(0);
  8858. }
  8859. /*
  8860. * clear the x25 connection - ie: hang up
  8861. */
  8862. int
  8863. x25clear() {
  8864. int get_flags = 0; /* priority flag for getmsg */
  8865. int put_flags = 0; /* send flags, always 0 */
  8866. ulong type; /* primitive type */
  8867. N_discon_req_t *discon_req; /* pointer to N_DISCON_REQ */
  8868. N_discon_ind_t *discon_ind; /* pointer to N_DISCON_IND */
  8869. N_npi_data_t *discon_data; /* pointer to N_DISCON_IND data */
  8870. int rc = 0; /* return code */
  8871. #ifdef TRACE
  8872. printf( "TRACE: entering x25clear\n" );
  8873. #endif /* TRACE */
  8874. #ifdef DEBUG
  8875. /* printf( "x25clear(): checking last msg: %s\n", x25prim(x25lastmsg)); */
  8876. #endif /* DEBUG */
  8877. /*
  8878. * The following checks are used to ensure that we don't disconnect
  8879. * or unbind twice - this seems to throw the NPI interface right out of
  8880. * kilter.
  8881. */
  8882. switch(x25lastmsg) {
  8883. case N_BIND_ACK:
  8884. case N_CONN_CON:
  8885. case N_CONN_REQ:
  8886. case N_DATA_REQ:
  8887. case N_DATA_IND:
  8888. {
  8889. #ifdef DEBUG
  8890. /* printf("x25clear(): actively disconnecting\n"); */
  8891. #endif /* DEBUG */
  8892. discon_req = (N_discon_req_t *)malloc(NPI_MAX_CTL);
  8893. if (discon_req == NULL) {
  8894. perror("kermit x25clear(): discon_req malloc failed\n");
  8895. /* fallthrough, try to unbind the NPI anyway */
  8896. } else {
  8897. discon_req->PRIM_type = N_DISCON_REQ;
  8898. discon_req->DISCON_reason = 0; /* not used by AIX */
  8899. discon_req->RES_length = 0;
  8900. discon_req->RES_offset = (ulong)(sizeof(N_discon_req_t));
  8901. discon_req->SEQ_number = x25seqno; /* global */
  8902. if (x25putmsg(ttyfd,
  8903. (N_npi_ctl_t*)discon_req,
  8904. (N_npi_data_t*)NULL,
  8905. 0,
  8906. &put_flags
  8907. ) < 0) {
  8908. perror("x25putmsg failed in x25clear()");
  8909. }
  8910. discon_ind = (N_discon_ind_t *)malloc(NPI_MAX_CTL);
  8911. discon_data = (N_npi_data_t *)malloc(NPI_MAX_DATA);
  8912. if((discon_ind == NULL) || (discon_data == NULL)) {
  8913. perror("x25clear(): discon_ind malloc failed\n");
  8914. /* fallthrough, try to unbind the NPI anyway */
  8915. } else {
  8916. if(x25getmsg(ttyfd,
  8917. (N_npi_ctl_t*)discon_ind,
  8918. NPI_MAX_CTL,
  8919. (N_npi_data_t*)discon_data,
  8920. NPI_MAX_DATA,
  8921. &get_flags,
  8922. N_OK_ACK
  8923. ) < 0 ) {
  8924. perror("x25getmsg failed in x25clear()");
  8925. /* fallthrough, try to unbind the NPI anyway */
  8926. }
  8927. }
  8928. }
  8929. break;
  8930. }
  8931. }
  8932. if (x25lastmsg != N_UNBIND_REQ) {
  8933. rc = x25unbind(ttyfd);
  8934. }
  8935. #ifdef TRACE
  8936. printf( "TRACE: leaving x25clear\n" );
  8937. #endif /* TRACE */
  8938. return(rc);
  8939. }
  8940. #ifdef DEBUG
  8941. /*
  8942. * only for debugging
  8943. *
  8944. * turn the internal representation of a datablock into something
  8945. * half-way readable. Because the length is known, we can print
  8946. * the string including null's etc (important, because the first(!)
  8947. * byte of an X121 address is a null! (X121 addr == 0 + X25 addr)
  8948. */
  8949. x25dump_data(char *addr, ulong offset, ulong length) {
  8950. char *ptr = addr + offset;
  8951. ulong i = length;
  8952. /* allocate enough memory for all unprintable chars */
  8953. char *buf = (char *)malloc( length * 4 );
  8954. char *bptr = buf; /* pointer to current place in the print buffer */
  8955. while (i > 0) {
  8956. if (isprint(*ptr)) {
  8957. *bptr++ = *ptr;
  8958. } else {
  8959. *bptr++ = '[';
  8960. strcpy(bptr,ckctox(*ptr,1)); bptr += 2;
  8961. *bptr++ = ']';
  8962. }
  8963. ptr++;
  8964. i--;
  8965. }
  8966. if (length > 0) {
  8967. *bptr = '\0';
  8968. printf( "%s", buf );
  8969. }
  8970. printf( " (%d+%d)\n", offset, length );
  8971. if (buf) { free(buf); buf = NULL; }
  8972. return;
  8973. }
  8974. /*
  8975. * only for debugging
  8976. * print as much useful information about a packet as possible
  8977. */
  8978. x25dump_prim(primitive) N_npi_ctl_t *primitive; {
  8979. printf("Primitive");
  8980. switch (primitive->PRIM_type) {
  8981. case N_BIND_ACK:
  8982. printf( "\tN_BIND_ACK\n\taddress:\t" );
  8983. x25dump_data( (char *)primitive,
  8984. primitive->bind_ack.ADDR_offset,
  8985. primitive->bind_ack.ADDR_length );
  8986. printf( "\tproto id:\t" );
  8987. x25dump_data( (char *)primitive,
  8988. primitive->bind_ack.PROTOID_offset,
  8989. primitive->bind_ack.PROTOID_length );
  8990. printf( "\tconnind:\t%d\n\ttoken:\t\t%d\n",
  8991. primitive->bind_ack.CONIND_number,
  8992. primitive->bind_ack.TOKEN_value );
  8993. break;
  8994. case N_BIND_REQ:
  8995. printf( "\tN_BIND_REQ\n\taddress:\t" );
  8996. x25dump_data( (char *)primitive,
  8997. primitive->bind_req.ADDR_offset,
  8998. primitive->bind_req.ADDR_length );
  8999. printf( "\tproto id:\t" );
  9000. x25dump_data( (char *)primitive,
  9001. primitive->bind_req.PROTOID_offset,
  9002. primitive->bind_req.PROTOID_length );
  9003. printf( "\tconnind:\t%d\n\tflags:\t\t%d\n",
  9004. primitive->bind_req.CONIND_number,
  9005. primitive->bind_req.BIND_flags );
  9006. break;
  9007. case N_CONN_CON:
  9008. printf( "\tN_CONN_CON\n" );
  9009. printf( "\tRES\t\t" );
  9010. x25dump_data( (char *)primitive,
  9011. primitive->conn_con.RES_offset,
  9012. primitive->conn_con.RES_length );
  9013. printf( "\tflags:\t%d\n", primitive->conn_con.CONN_flags );
  9014. break;
  9015. case N_CONN_IND:
  9016. printf( "\tN_CONN_IND\n" );
  9017. printf( "\tsource:\t\t" );
  9018. x25dump_data( (char *)primitive,
  9019. primitive->conn_ind.SRC_offset,
  9020. primitive->conn_ind.SRC_length );
  9021. printf( "\tdestination:\t" );
  9022. x25dump_data( (char *)primitive,
  9023. primitive->conn_ind.DEST_offset,
  9024. primitive->conn_ind.DEST_length );
  9025. printf( "\tSEQ_number:\t%d\n", primitive->conn_ind.SEQ_number );
  9026. printf( "\tflags:\t%d\n", primitive->conn_ind.CONN_flags );
  9027. break;
  9028. case N_CONN_REQ:
  9029. printf( "\tN_CONN_REQ\n\tdestination:\t" );
  9030. x25dump_data( (char *)primitive,
  9031. primitive->conn_req.DEST_offset,
  9032. primitive->conn_req.DEST_length );
  9033. printf( "\tflags:\t%d\n", primitive->conn_req.CONN_flags );
  9034. break;
  9035. case N_CONN_RES:
  9036. printf( "\tN_CONN_RES\n" );
  9037. printf( "\tTOKEN_value\t%d\n", primitive->conn_res.TOKEN_value );
  9038. printf( "\tSEQ_number\t%d\n", primitive->conn_res.SEQ_number );
  9039. printf( "\tCONN_flags\t%d\n", primitive->conn_res.CONN_flags );
  9040. printf( "\tRES\t\t" );
  9041. x25dump_data( (char *)primitive,
  9042. primitive->conn_res.RES_offset,
  9043. primitive->conn_res.RES_length );
  9044. break;
  9045. case N_DATACK_IND:
  9046. printf( "\tN_DATACK_IND\n" );
  9047. break;
  9048. case N_DATACK_REQ:
  9049. printf( "\tN_DATACK_REQ\n" );
  9050. printf( "\tflags:\t%d\n", primitive->data_req.DATA_xfer_flags );
  9051. break;
  9052. case N_DATA_IND:
  9053. printf( "\tN_DATA_IND\n" );
  9054. printf( "\tflags:\t%d\n", primitive->data_ind.DATA_xfer_flags );
  9055. break;
  9056. case N_DATA_REQ:
  9057. printf( "\tN_DATA_REQ\n" );
  9058. break;
  9059. case N_DISCON_IND:
  9060. printf( "\tN_DISCON_IND\n" );
  9061. printf( "\torigin:\t%d\n", primitive->discon_ind.DISCON_orig );
  9062. printf( "\treason:\t\t%d\n", primitive->discon_ind.DISCON_reason );
  9063. printf( "\tseq no:\t\t%d\n", primitive->discon_ind.SEQ_number );
  9064. printf( "\tRES:\t" );
  9065. x25dump_data( (char *)primitive,
  9066. primitive->discon_ind.RES_offset,
  9067. primitive->discon_ind.RES_length );
  9068. break;
  9069. case N_DISCON_REQ:
  9070. printf( "\tN_DISCON_REQ\n" );
  9071. printf( "\tDISCON_reason:\t%d\n",
  9072. primitive->discon_req.DISCON_reason );
  9073. printf( "\tRES:\t" );
  9074. x25dump_data( (char *)primitive,
  9075. primitive->discon_req.RES_offset,
  9076. primitive->discon_req.RES_length );
  9077. printf( "\tSEQ_number:\t%d\n", primitive->discon_req.SEQ_number );
  9078. break;
  9079. case N_ERROR_ACK:
  9080. printf( "\tN_ERROR_ACK\n" );
  9081. printf( "\tCaused by:\t%s\n",
  9082. x25prim( primitive->error_ack.ERROR_prim ) );
  9083. printf( "\tNPI error:\t%s\n",
  9084. x25err( primitive->error_ack.NPI_error ));
  9085. errno = primitive->error_ack.UNIX_error;
  9086. perror( "\t" );
  9087. break;
  9088. case N_EXDATA_IND:
  9089. printf( "\tN_EXDATA_ACK\n" );
  9090. break;
  9091. case N_EXDATA_REQ:
  9092. printf( "\tN_EXDATA_REQ\n" );
  9093. break;
  9094. case N_INFO_ACK:
  9095. printf( "\tN_INFO_ACK\n" );
  9096. printf( "\tNSDU size:\t%d\n", primitive->info_ack.NSDU_size );
  9097. printf( "\tENSDU size:\t%d\n", primitive->info_ack.ENSDU_size );
  9098. printf( "\tCDATA size:\t%d\n", primitive->info_ack.CDATA_size );
  9099. printf( "\tDDATA size:\t%d\n", primitive->info_ack.DDATA_size );
  9100. printf( "\tADDR size:\t%d\n", primitive->info_ack.ADDR_size );
  9101. printf( "\tNIDU size:\t%d\n", primitive->info_ack.NIDU_size );
  9102. break;
  9103. case N_INFO_REQ:
  9104. printf( "\tN_INFO_REQ\n" );
  9105. break;
  9106. case N_OK_ACK:
  9107. printf( "\tN_OK_ACK\n" );
  9108. break;
  9109. case N_OPTMGMT_REQ:
  9110. printf( "\tN_OPTMGMT_REQ\n" );
  9111. break;
  9112. case N_RESET_CON:
  9113. printf( "\tN_RESET_CON\n" );
  9114. break;
  9115. case N_RESET_IND:
  9116. printf( "\tN_RESET_IND\n" );
  9117. printf( "\treason:\t\t%d\n", primitive->reset_ind.RESET_reason );
  9118. printf( "\torigin:\t\t%d\n", primitive->reset_ind.RESET_orig );
  9119. break;
  9120. case N_RESET_REQ:
  9121. printf( "\tN_RESET_REQ\n" );
  9122. printf( "\treason:\t\t%d\n", primitive->reset_req.RESET_reason );
  9123. break;
  9124. case N_RESET_RES:
  9125. printf( "\tN_RESET_RES\n" );
  9126. break;
  9127. case N_UDERROR_IND:
  9128. printf( "\tN_UDERROR_IND\n" );
  9129. break;
  9130. case N_UNBIND_REQ:
  9131. printf( "\tN_UNBIND_REQ\n" );
  9132. break;
  9133. case N_UNITDATA_REQ:
  9134. printf( "\tN_UNITDATA_REQ\n" );
  9135. break;
  9136. case N_UNITDATA_IND:
  9137. printf( "\tN_UNITDATA_IND\n" );
  9138. break;
  9139. default:
  9140. (void) printf( "Unknown NPI error %d", primitive->PRIM_type );
  9141. return 0;
  9142. }
  9143. }
  9144. #endif /* DEBUG */
  9145. /* it looks like signal handling is not needed with streams! */
  9146. /* x25oobh() - handle SIGURG signals - take from isode ? */
  9147. #endif /* IBMX25 */
  9148. #ifndef NOHTTP
  9149. /*
  9150. Which time.h files to include... See ckcdeb.h for defaults.
  9151. Note that 0, 1, 2, or all 3 of these can be included according to
  9152. the symbol definitions.
  9153. */
  9154. #ifndef NOTIMEH
  9155. #ifdef TIMEH
  9156. #include <time.h>
  9157. #endif /* TIMEH */
  9158. #endif /* NOTIMEH */
  9159. #ifndef NOSYSTIMEH
  9160. #ifdef SYSTIMEH
  9161. #include <sys/time.h>
  9162. #endif /* SYSTIMEH */
  9163. #endif /* NOSYSTIMEH */
  9164. #ifndef NOSYSTIMEBH
  9165. #ifdef SYSTIMEBH
  9166. #include <sys/timeb.h>
  9167. #endif /* SYSTIMEBH */
  9168. #endif /* NOSYSTIMEBH */
  9169. #ifndef TIMEH
  9170. #ifndef SYSTIMEH
  9171. #ifndef SYSTIMEBH
  9172. #ifdef Plan9
  9173. #include <sys/time.h>
  9174. #else
  9175. #ifdef AIX41
  9176. #include <time.h>
  9177. #else
  9178. #ifdef SUNOS4
  9179. #include <sys/time.h>
  9180. #else
  9181. #ifdef SYSTIMEH
  9182. #include <sys/time.h>
  9183. #else
  9184. #ifdef POSIX
  9185. #include <posix/time.h>
  9186. #else
  9187. #ifdef CLIX
  9188. #include <sys/time.h>
  9189. #else
  9190. #ifdef OS2
  9191. #include <time.h>
  9192. #else
  9193. #include <time.h>
  9194. /* #include <utime.h> */
  9195. #endif /* OS2 */
  9196. #endif /* CLIX */
  9197. #endif /* POSIX */
  9198. #endif /* SYSTIMEH */
  9199. #endif /* SUNOS4 */
  9200. #endif /* AIX41 */
  9201. #endif /* Plan9 */
  9202. #endif
  9203. #endif
  9204. #endif
  9205. #ifdef OS2
  9206. #include <sys/utime.h>
  9207. #ifdef NT
  9208. #define utimbuf _utimbuf
  9209. #endif /* NT */
  9210. #define utime _utime
  9211. #else
  9212. #ifdef SYSUTIMEH /* <sys/utime.h> if requested, */
  9213. #include <sys/utime.h> /* for extra fields required by */
  9214. #else /* 88Open spec. */
  9215. #ifdef UTIMEH /* or <utime.h> if requested */
  9216. #include <utime.h> /* (SVR4, POSIX) */
  9217. #define SYSUTIMEH /* Use this for both cases. */
  9218. #endif /* UTIMEH */
  9219. #endif /* SYSUTIMEH */
  9220. #endif /* OS2 */
  9221. #ifdef VMS /* SMS 2007/02/15 */
  9222. #include "ckvrtl.h"
  9223. #endif /* def VMS */
  9224. #ifndef HTTP_VERSION
  9225. #define HTTP_VERSION "HTTP/1.1"
  9226. #endif /* HTTP_VERSION */
  9227. #ifdef CMDATE2TM
  9228. time_t
  9229. #ifdef CK_ANSIC
  9230. http_date(char * date)
  9231. #else
  9232. http_date(date) char * date;
  9233. #endif /* CK_ANSIC */
  9234. /* http_date */ {
  9235. /* HTTP dates are of the form: "Sun, 06 Oct 1997 20:11:47 GMT" */
  9236. /* There are two older formats which we are required to parse
  9237. * that we currently do not:
  9238. *
  9239. * RFC 850: "Sunday, 06-Oct-97 20:11:47 GMT"
  9240. * asctime(): "Sun Nov 6 20:11:47 1997"
  9241. *
  9242. * However, it is required that all dates be sent in the form we
  9243. * do accept. The other two formats are for compatibility with
  9244. * really old servers.
  9245. */
  9246. extern char cmdatebuf[18];
  9247. struct tm t_tm;
  9248. time_t t;
  9249. char ldate[32];
  9250. int j;
  9251. j = ckindex(",",date,0,0,0);
  9252. ckstrncpy(ldate,&date[j+1],25);
  9253. { /*
  9254. cmcvtate() date changed to return a string pointer.
  9255. fdc, 12 Aug 2001.
  9256. */
  9257. char * dp;
  9258. dp = (char *)cmcvtdate(ldate,0); /* Convert to normal form */
  9259. if (!dp)
  9260. return(0);
  9261. t_tm = *cmdate2tm(dp,1);
  9262. }
  9263. /*
  9264. From Lucas Hart, 5 Dec 2001:
  9265. "On the systems to which I have access (SunOS 4.1.1, Solaris 8, and Tru64),
  9266. setting tm_isdst to -1 maintains the correct timezone offsets, i.e., writes
  9267. the specified (GMT) time if the buffer size is 21, or the contemporaneous
  9268. localtime if the buffer size is 25. Perhaps tm_isdst should be set in
  9269. cmdate2tm(), rather than only in http_date."
  9270. */
  9271. #ifndef NOTM_ISDST /* For platforms where */
  9272. t_tm.tm_isdst = -1; /* tm_isdst doesn't exist. */
  9273. #endif /* NOTM_ISDST */
  9274. t = mktime(&t_tm); /* NOT PORTABLE */
  9275. #ifdef XX_TIMEZONE
  9276. t -= _timezone;
  9277. #endif /* XX_TIMEZONE */
  9278. return(t);
  9279. }
  9280. #endif /* CMDATE2TM */
  9281. char *
  9282. http_now() {
  9283. static char nowstr[32];
  9284. #ifdef CMDATE2TM
  9285. struct tm *gmt;
  9286. time_t ltime; /* NOT PORTABLE */
  9287. time(&ltime);
  9288. gmt = gmtime(&ltime); /* PROBABLY NOT PORTABLE */
  9289. strftime(nowstr,32,"%a, %d %b %Y %H:%M:%S GMT",gmt); /* NOT PORTABLE */
  9290. /* not only is it not portable but it's locale-dependent */
  9291. #else
  9292. /*
  9293. This is hopeless. First of all, it seems that HTTP wants Day and Month
  9294. NAMES? In English? Whose idea was that? Even worse, the date/time must be
  9295. expressed in Zulu (UTC (GMT)), and converting from local time to GMT is a
  9296. nightmare. Every platform does it differently, if at all -- even if we
  9297. restrict ourselves to UNIX. For example (quoting from recent C-Kermit edit
  9298. history), "Fixed a longstanding bug in the BSDI version, in which incoming
  9299. file dates were set in GMT rather than local time. It seems in 4.4BSD,
  9300. localtime() does not return the local time, but rather Zero Meridian (Zulu)
  9301. time (GMT), and must be adjusted by the tm_gmtoff value." Swell. For
  9302. greater appreciation of the scope of the problem, just take a look at the
  9303. time-related #ifdefs in ckutio.c. The only right way to do this is to add
  9304. our own portable API for converting between local time and GMT/UTC/Zulu
  9305. that shields us not only from UNIXisms like time_t and struct tm, but also
  9306. the unbelievable amount of differences in time-related APIs -- e.g. is
  9307. "timezone" an external variable or a function; which header file(s) do we
  9308. include, etc etc etc. It's a major project.
  9309. */
  9310. int x;
  9311. x = cmcvtdate("",1);
  9312. Evidently this code is not used -- if it is, it must be fixed to use
  9313. new (aug 2001) cmcvtdate() calling conventions.
  9314. if (x < 0)
  9315. return("");
  9316. /* yyyymmdd hh:mm:ss */
  9317. /* 01234567890123456 */
  9318. nowstr[0] = 'X'; /* 1st letter of day */
  9319. nowstr[1] = 'x'; /* 2nd letter of day */
  9320. nowstr[2] = 'x'; /* 3rd letter of day */
  9321. nowstr[3] = ',';
  9322. nowstr[4] = ' ';
  9323. nowstr[5] = cmdate[6];
  9324. nowstr[6] = cmdate[7];
  9325. nowstr[7] = ' ';
  9326. nowstr[8] = ' '; /* first letter of month */
  9327. nowstr[9] = ' '; /* second letter of month */
  9328. nowstr[10] = ' '; /* third letter of month */
  9329. nowstr[11] = ' ';
  9330. nowstr[12] = cmdate[0];
  9331. nowstr[13] = cmdate[1];
  9332. nowstr[14] = cmdate[2];
  9333. nowstr[15] = cmdate[3];
  9334. nowstr[16] = ' ';
  9335. nowstr[17] = cmdate[9];
  9336. nowstr[18] = cmdate[10];
  9337. nowstr[19] = cmdate[11];
  9338. nowstr[20] = cmdate[12];
  9339. nowstr[21] = cmdate[13];
  9340. nowstr[22] = cmdate[14];
  9341. nowstr[23] = cmdate[15];
  9342. nowstr[24] = cmdate[16];
  9343. nowstr[25] = ' ';
  9344. nowstr[26] = 'G';
  9345. nowstr[27] = 'M';
  9346. nowstr[28] = 'T';
  9347. nowstr[29] = '\0';
  9348. #endif /* CMDATE2TM */
  9349. return(nowstr);
  9350. }
  9351. #ifndef OS2
  9352. #ifndef CK_AUTHENTICATION
  9353. /* from ckuusr.h, which this module normally doesn't include */
  9354. _PROTOTYP( int dclarray, (char, int) );
  9355. #endif /* CK_AUTHENTICATION */
  9356. #endif /* OS2 */
  9357. /*
  9358. Assign http response pairs to given array.
  9359. For best results, response pairs should contain no spaces.
  9360. Call with:
  9361. resp = pointer to response list.
  9362. n = size of response list.
  9363. array = array letter.
  9364. Returns:
  9365. 0 on failure.
  9366. >= 1, size of array, on success.
  9367. */
  9368. static int
  9369. #ifdef CK_ANSIC
  9370. http_mkarray(char ** resp, int n, char array)
  9371. #else
  9372. http_mkarray(resp, n, array) char ** resp; int n; char array;
  9373. #endif /* CK_ANSIC */
  9374. {
  9375. #ifndef NOSPL
  9376. int i, x;
  9377. char ** ap;
  9378. extern char ** a_ptr[];
  9379. extern int a_dim[];
  9380. if (!array || n <= 0)
  9381. return(0);
  9382. if ((x = dclarray(array,n)) < 0) {
  9383. printf("?Array declaration failure\n");
  9384. return(-9);
  9385. }
  9386. /* Note: argument array is 0-based but Kermit array is 1-based */
  9387. ap = a_ptr[x];
  9388. ap[0] = NULL; /* 0th element is empty */
  9389. for (i = 1; i <= n; i++) {
  9390. ap[i] = resp[i-1]; /* If resp elements were malloc'd */
  9391. resp[i-1] = NULL;
  9392. }
  9393. a_dim[x] = n;
  9394. return(n);
  9395. #else
  9396. return(0);
  9397. #endif /* NOSPL */
  9398. }
  9399. #define HTTPHEADCNT 64
  9400. int
  9401. http_get_chunk_len()
  9402. {
  9403. int len = 0;
  9404. int i = 0, j = -1;
  9405. char buf[24];
  9406. int ch;
  9407. while ((ch = http_inc(0)) >= 0 && i < 24) {
  9408. buf[i] = ch;
  9409. if ( buf[i] == ';' ) /* Find chunk-extension (if any) */
  9410. j = i;
  9411. if ( buf[i] == 10 ) { /* found end of line */
  9412. if (i > 0 && buf[i-1] == 13)
  9413. i--;
  9414. buf[i] = '\0';
  9415. break;
  9416. }
  9417. i++;
  9418. }
  9419. if ( i < 24 ) { /* buf now contains len in Hex */
  9420. len = hextoulong(buf, j == -1 ? i : j-1);
  9421. }
  9422. return(len);
  9423. }
  9424. int
  9425. http_isconnected()
  9426. {
  9427. return(httpfd != -1);
  9428. }
  9429. char *
  9430. http_host()
  9431. {
  9432. return(httpfd != -1 ? http_host_port : "");
  9433. }
  9434. char *
  9435. http_security()
  9436. {
  9437. if ( httpfd == -1 )
  9438. return("NULL");
  9439. #ifdef CK_SSL
  9440. if (tls_http_active_flag) {
  9441. SSL_CIPHER * cipher;
  9442. const char *cipher_list;
  9443. static char buf[128];
  9444. buf[0] = NUL;
  9445. cipher = SSL_get_current_cipher(tls_http_con);
  9446. cipher_list = SSL_CIPHER_get_name(cipher);
  9447. SSL_CIPHER_description(cipher,buf,sizeof(buf));
  9448. return(buf);
  9449. }
  9450. #endif /* CK_SSL */
  9451. return("NULL");
  9452. }
  9453. int
  9454. http_reopen()
  9455. {
  9456. int rc = 0;
  9457. char * s = NULL; /* strdup is not portable */
  9458. if ( tcp_http_proxy ) {
  9459. char * p;
  9460. makestr(&s,(char *)http_host_port);
  9461. p = s;
  9462. while (*p != '\0' && *p != ':') p++; /* Look for colon */
  9463. if (*p == ':') { /* Have a colon */
  9464. *p++ = '\0'; /* Get service name or number */
  9465. } else {
  9466. p="http";
  9467. }
  9468. rc = http_open(s,p,http_ssl,NULL,0,http_agent);
  9469. } else {
  9470. makestr(&s,(char *)http_ip);
  9471. rc = http_open(s,ckuitoa(http_port),http_ssl,NULL,0,http_agent);
  9472. }
  9473. free(s);
  9474. return(rc);
  9475. }
  9476. int
  9477. #ifdef CK_ANSIC
  9478. http_open(char * hostname, char * svcname, int use_ssl, char * rdns_name,
  9479. int rdns_len, char * agent)
  9480. #else /* CK_ANSIC */
  9481. http_open(hostname, svcname, use_ssl, rdns_name, rdns_len, agent)
  9482. char * hostname;
  9483. char * svcname;
  9484. int use_ssl;
  9485. char * rdns_name;
  9486. int rdns_len;
  9487. char * agent;
  9488. #endif /* CK_ANSIC */
  9489. {
  9490. char namecopy[NAMECPYL];
  9491. char *p;
  9492. int i, x, dns = 0;
  9493. #ifdef TCPSOCKET
  9494. int isconnect = 0;
  9495. #ifdef SO_OOBINLINE
  9496. int on = 1;
  9497. #endif /* SO_OOBINLINE */
  9498. struct servent *service=NULL;
  9499. struct hostent *host=NULL;
  9500. struct sockaddr_in r_addr;
  9501. struct sockaddr_in sin;
  9502. struct sockaddr_in l_addr;
  9503. GSOCKNAME_T l_slen;
  9504. #ifdef EXCELAN
  9505. struct sockaddr_in send_socket;
  9506. #endif /* EXCELAN */
  9507. #ifdef INADDRX
  9508. /* inet_addr() is of type struct in_addr */
  9509. #ifdef datageneral
  9510. extern struct in_addr inet_addr();
  9511. #else
  9512. #ifdef HPUX5WINTCP
  9513. extern struct in_addr inet_addr();
  9514. #endif /* HPUX5WINTCP */
  9515. #endif /* datageneral */
  9516. struct in_addr iax;
  9517. #else
  9518. #ifdef INADDR_NONE
  9519. struct in_addr iax;
  9520. #else /* INADDR_NONE */
  9521. long iax;
  9522. #endif /* INADDR_NONE */
  9523. #endif /* INADDRX */
  9524. if ( rdns_name == NULL || rdns_len < 0 )
  9525. rdns_len = 0;
  9526. *http_ip = '\0'; /* Initialize IP address string */
  9527. namecopy[0] = '\0';
  9528. #ifdef DEBUG
  9529. if (deblog) {
  9530. debug(F110,"http_open hostname",hostname,0);
  9531. debug(F110,"http_open svcname",svcname,0);
  9532. }
  9533. #endif /* DEBUG */
  9534. if (!hostname) hostname = "";
  9535. if (!svcname) svcname = "";
  9536. if (!*hostname || !*svcname) return(-1);
  9537. service = ckgetservice(hostname,svcname,http_ip,20);
  9538. if (service == NULL) {
  9539. if ( !quiet )
  9540. printf("?Invalid service: %s\r\n",svcname);
  9541. return(-1);
  9542. }
  9543. /* For HTTP connections we must preserve the original hostname and */
  9544. /* service requested so we can include them in the Host header. */
  9545. ckmakmsg(http_host_port,sizeof(http_host_port),hostname,":",
  9546. ckuitoa(ntohs(service->s_port)),NULL);
  9547. http_port = ntohs(service->s_port);
  9548. http_ssl = use_ssl;
  9549. debug(F111,"http_open",http_host_port,http_port);
  9550. /* 'http_ip' contains the IP address to which we want to connect */
  9551. /* 'svcnam' contains the service name */
  9552. /* 'service->s_port' contains the port number in network byte order */
  9553. /* If we are using an http proxy, we need to create a buffer containing */
  9554. /* hostname:port-number */
  9555. /* to pass to the http_connect() function. Then we need to replace */
  9556. /* 'namecopy' with the name of the proxy server and the service->s_port */
  9557. /* with the port number of the proxy (default port 80). */
  9558. if ( tcp_http_proxy ) {
  9559. ckmakmsg(proxycopy,sizeof(proxycopy),hostname,":",
  9560. ckuitoa(ntohs(service->s_port)),NULL);
  9561. ckstrncpy(namecopy,tcp_http_proxy,NAMECPYL);
  9562. p = namecopy; /* Was a service requested? */
  9563. while (*p != '\0' && *p != ':') p++; /* Look for colon */
  9564. if (*p == ':') { /* Have a colon */
  9565. debug(F110,"http_open name has colon",namecopy,0);
  9566. *p++ = '\0'; /* Get service name or number */
  9567. } else {
  9568. strcpy(++p,"http");
  9569. }
  9570. service = ckgetservice(namecopy,p,http_ip,20);
  9571. if (!service) {
  9572. fprintf(stderr, "Can't find port for service %s\n", p);
  9573. #ifdef TGVORWIN
  9574. debug(F101,"http_open can't get service for proxy","",socket_errno);
  9575. #else
  9576. debug(F101,"http_open can't get service for proxy","",errno);
  9577. #endif /* TGVORWIN */
  9578. errno = 0; /* (rather than mislead) */
  9579. return(-1);
  9580. }
  9581. /* copy the proxyname and remove the service if any so we can use
  9582. * it as the hostname
  9583. */
  9584. ckstrncpy(namecopy,tcp_http_proxy,NAMECPYL);
  9585. p = namecopy; /* Was a service requested? */
  9586. while (*p != '\0' && *p != ':') p++; /* Look for colon */
  9587. if (*p == ':') { /* Have a colon */
  9588. *p = '\0'; /* terminate string */
  9589. }
  9590. hostname = namecopy; /* use proxy as hostname */
  9591. }
  9592. /* Set up socket structure and get host address */
  9593. bzero((char *)&r_addr, sizeof(r_addr));
  9594. debug(F100,"http_open bzero ok","",0);
  9595. #ifdef INADDR_NONE
  9596. debug(F101,"http_open INADDR_NONE defined","",INADDR_NONE);
  9597. #else /* INADDR_NONE */
  9598. debug(F100,"http_open INADDR_NONE not defined","",0);
  9599. #endif /* INADDR_NONE */
  9600. #ifdef INADDRX
  9601. debug(F100,"http_open INADDRX defined","",0);
  9602. #else /* INADDRX */
  9603. debug(F100,"http_open INADDRX not defined","",0);
  9604. #endif /* INADDRX */
  9605. #ifndef NOMHHOST
  9606. #ifdef INADDRX
  9607. iax = inet_addr(http_ip[0]?http_ip:hostname);
  9608. debug(F111,"http_open inet_addr",http_ip[0]?http_ip:hostname,iax.s_addr);
  9609. #else /* INADDRX */
  9610. #ifdef INADDR_NONE
  9611. iax.s_addr = inet_addr(http_ip[0]?http_ip:hostname);
  9612. debug(F111,"http_open inet_addr",http_ip[0]?http_ip:hostname,iax.s_addr);
  9613. #else /* INADDR_NONE */
  9614. #ifndef datageneral
  9615. iax = (unsigned int) inet_addr(http_ip[0]?http_ip:hostname);
  9616. #else
  9617. iax = -1L;
  9618. #endif /* datageneral */
  9619. debug(F111,"http_open inet_addr",http_ip[0]?http_ip:hostname,iax);
  9620. #endif /* INADDR_NONE */
  9621. #endif /* INADDRX */
  9622. dns = 0;
  9623. if (
  9624. #ifdef INADDR_NONE
  9625. /* This might give warnings on 64-bit platforms but they should be harmless */
  9626. /* because INADDR_NONE should be all 1's anyway, thus the OR part is */
  9627. /* probably superfluous -- not sure why it's even there, maybe it should be */
  9628. /* removed. */
  9629. iax.s_addr == INADDR_NONE /* || iax.s_addr == (unsigned long) -1L */
  9630. #else /* INADDR_NONE */
  9631. iax == -1
  9632. #endif /* INADDR_NONE */
  9633. ) {
  9634. if (!quiet) {
  9635. printf(" DNS Lookup... ");
  9636. fflush(stdout);
  9637. }
  9638. if ((host = gethostbyname(http_ip[0] ? http_ip : hostname)) != NULL) {
  9639. debug(F100,"http_open gethostbyname != NULL","",0);
  9640. host = ck_copyhostent(host);
  9641. dns = 1; /* Remember we performed dns lookup */
  9642. r_addr.sin_family = host->h_addrtype;
  9643. if (tcp_rdns && host->h_name && host->h_name[0] && (rdns_len > 0)
  9644. && (tcp_http_proxy == NULL)
  9645. )
  9646. ckmakmsg(rdns_name,rdns_len,host->h_name,":",svcname,NULL);
  9647. #ifdef HADDRLIST
  9648. #ifdef h_addr
  9649. /* This is for trying multiple IP addresses - see <netdb.h> */
  9650. if (!(host->h_addr_list))
  9651. return(-1);
  9652. bcopy(host->h_addr_list[0],
  9653. (caddr_t)&r_addr.sin_addr,
  9654. host->h_length
  9655. );
  9656. #else
  9657. bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
  9658. #endif /* h_addr */
  9659. #else /* HADDRLIST */
  9660. bcopy(host->h_addr, (caddr_t)&r_addr.sin_addr, host->h_length);
  9661. #endif /* HADDRLIST */
  9662. #ifdef COMMENT
  9663. #ifndef EXCELAN
  9664. debug(F111,"BCOPY","host->h_addr",host->h_addr);
  9665. #endif /* EXCELAN */
  9666. debug(F111,"BCOPY"," (caddr_t)&r_addr.sin_addr",
  9667. (caddr_t)&r_addr.sin_addr);
  9668. debug(F111,"BCOPY"," r_addr.sin_addr.s_addr",
  9669. r_addr.sin_addr.s_addr);
  9670. #endif /* COMMENT */
  9671. debug(F111,"BCOPY","host->h_length",host->h_length);
  9672. }
  9673. }
  9674. #endif /* NOMHHOST */
  9675. if (!dns) {
  9676. #ifdef INADDRX
  9677. /* inet_addr() is of type struct in_addr */
  9678. struct in_addr ina;
  9679. unsigned long uu;
  9680. debug(F100,"http_open gethostbyname == NULL: INADDRX","",0);
  9681. ina = inet_addr(http_ip[0]?http_ip:hostname);
  9682. uu = *(unsigned int *)&ina;
  9683. #else /* Not INADDRX */
  9684. /* inet_addr() is unsigned long */
  9685. unsigned long uu;
  9686. debug(F100,"http_open gethostbyname == NULL: Not INADDRX","",0);
  9687. uu = inet_addr(http_ip[0]?http_ip:hostname);
  9688. #endif /* INADDRX */
  9689. debug(F101,"http_open uu","",uu);
  9690. if (
  9691. #ifdef INADDR_NONE
  9692. !(uu == INADDR_NONE || uu == (unsigned int) -1L)
  9693. #else /* INADDR_NONE */
  9694. uu != ((unsigned long)-1)
  9695. #endif /* INADDR_NONE */
  9696. ) {
  9697. r_addr.sin_addr.s_addr = uu;
  9698. r_addr.sin_family = AF_INET;
  9699. } else {
  9700. #ifdef VMS
  9701. fprintf(stdout, "\r\n"); /* complete any previous message */
  9702. #endif /* VMS */
  9703. fprintf(stderr, "Can't get address for %s\n",
  9704. http_ip[0]?http_ip:hostname);
  9705. #ifdef TGVORWIN
  9706. debug(F101,"http_open can't get address","",socket_errno);
  9707. #else
  9708. debug(F101,"http_open can't get address","",errno);
  9709. #endif /* TGVORWIN */
  9710. errno = 0; /* Rather than mislead */
  9711. return(-1);
  9712. }
  9713. }
  9714. /* Get a file descriptor for the connection. */
  9715. r_addr.sin_port = service->s_port;
  9716. ckstrncpy(http_ip,(char *)inet_ntoa(r_addr.sin_addr),20);
  9717. debug(F110,"http_open trying",http_ip,0);
  9718. if (!quiet && *http_ip) {
  9719. printf(" Trying %s... ", http_ip);
  9720. fflush(stdout);
  9721. }
  9722. /* Loop to try additional IP addresses, if any. */
  9723. do {
  9724. #ifdef EXCELAN
  9725. send_socket.sin_family = AF_INET;
  9726. send_socket.sin_addr.s_addr = 0;
  9727. send_socket.sin_port = 0;
  9728. if ((httpfd = socket(SOCK_STREAM, (struct sockproto *)0,
  9729. &send_socket, SO_REUSEADDR)) < 0)
  9730. #else /* EXCELAN */
  9731. if ((httpfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  9732. #endif /* EXCELAN */
  9733. {
  9734. #ifdef EXCELAN
  9735. experror("TCP socket error");
  9736. #else
  9737. #ifdef TGVORWIN
  9738. #ifdef OLD_TWG
  9739. errno = socket_errno;
  9740. #endif /* OLD_TWG */
  9741. socket_perror("TCP socket error");
  9742. debug(F101,"http_open socket error","",socket_errno);
  9743. #else
  9744. perror("TCP socket error");
  9745. debug(F101,"http_open socket error","",errno);
  9746. #endif /* TGVORWIN */
  9747. #endif /* EXCELAN */
  9748. return (-1);
  9749. }
  9750. errno = 0;
  9751. /* If a specific TCP address on the local host is desired we */
  9752. /* must bind it to the socket. */
  9753. #ifndef datageneral
  9754. if (tcp_address) {
  9755. int s_errno;
  9756. debug(F110,"http_open binding socket to",tcp_address,0);
  9757. bzero((char *)&sin,sizeof(sin));
  9758. sin.sin_family = AF_INET;
  9759. #ifdef INADDRX
  9760. inaddrx = inet_addr(tcp_address);
  9761. sin.sin_addr.s_addr = *(unsigned long *)&inaddrx;
  9762. #else
  9763. sin.sin_addr.s_addr = inet_addr(tcp_address);
  9764. #endif /* INADDRX */
  9765. sin.sin_port = 0;
  9766. if (bind(httpfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
  9767. s_errno = socket_errno; /* Save error code */
  9768. #ifdef TCPIPLIB
  9769. socket_close(httpfd);
  9770. #else /* TCPIPLIB */
  9771. close(httpfd);
  9772. #endif /* TCPIPLIB */
  9773. httpfd = -1;
  9774. errno = s_errno; /* and report this error */
  9775. debug(F101,"http_open bind errno","",errno);
  9776. return(-1);
  9777. }
  9778. }
  9779. #endif /* datageneral */
  9780. /* Now connect to the socket on the other end. */
  9781. #ifdef EXCELAN
  9782. if (connect(httpfd, &r_addr) < 0)
  9783. #else
  9784. #ifdef NT
  9785. WSASafeToCancel = 1;
  9786. #endif /* NT */
  9787. if (connect(httpfd, (struct sockaddr *)&r_addr, sizeof(r_addr)) < 0)
  9788. #endif /* EXCELAN */
  9789. {
  9790. #ifdef NT
  9791. WSASafeToCancel = 0;
  9792. #endif /* NT */
  9793. #ifdef OS2
  9794. i = socket_errno;
  9795. #else /* OS2 */
  9796. #ifdef TGVORWIN
  9797. i = socket_errno;
  9798. #else
  9799. i = errno; /* Save error code */
  9800. #endif /* TGVORWIN */
  9801. #endif /* OS2 */
  9802. #ifdef HADDRLIST
  9803. #ifdef h_addr
  9804. if (host && host->h_addr_list && host->h_addr_list[1]) {
  9805. perror("");
  9806. host->h_addr_list++;
  9807. bcopy(host->h_addr_list[0],
  9808. (caddr_t)&r_addr.sin_addr,
  9809. host->h_length);
  9810. ckstrncpy(http_ip,(char *)inet_ntoa(r_addr.sin_addr),20);
  9811. debug(F110,"http_open h_addr_list",http_ip,0);
  9812. if (!quiet && *http_ip) {
  9813. printf(" Trying %s... ", http_ip);
  9814. fflush(stdout);
  9815. }
  9816. #ifdef TCPIPLIB
  9817. socket_close(httpfd); /* Close it. */
  9818. #else
  9819. close(httpfd);
  9820. #endif /* TCPIPLIB */
  9821. continue;
  9822. }
  9823. #endif /* h_addr */
  9824. #endif /* HADDRLIST */
  9825. http_close();
  9826. httpfd = -1;
  9827. errno = i; /* And report this error */
  9828. #ifdef EXCELAN
  9829. if (errno) experror("http_open connect");
  9830. #else
  9831. #ifdef TGVORWIN
  9832. debug(F101,"http_open connect error","",socket_errno);
  9833. /* if (errno) socket_perror("http_open connect"); */
  9834. #ifdef OLD_TWG
  9835. errno = socket_errno;
  9836. #endif /* OLD_TWG */
  9837. if (!quiet)
  9838. socket_perror("http_open connect");
  9839. #else /* TGVORWIN */
  9840. debug(F101,"http_open connect errno","",errno);
  9841. #ifdef VMS
  9842. if (!quiet)
  9843. perror("\r\nFailed");
  9844. #else
  9845. if (!quiet)
  9846. perror("Failed");
  9847. #endif /* VMS */
  9848. #ifdef DEC_TCPIP
  9849. if (!quiet)
  9850. perror("http_open connect");
  9851. #endif /* DEC_TCPIP */
  9852. #ifdef CMU_TCPIP
  9853. if (!quiet)
  9854. perror("http_open connect");
  9855. #endif /* CMU_TCPIP */
  9856. #endif /* TGVORWIN */
  9857. #endif /* EXCELAN */
  9858. return(-1);
  9859. }
  9860. #ifdef NT
  9861. WSASafeToCancel = 0;
  9862. #endif /* NT */
  9863. isconnect = 1;
  9864. } while (!isconnect);
  9865. #ifdef NON_BLOCK_IO
  9866. on = 1;
  9867. x = socket_ioctl(httpfd,FIONBIO,&on);
  9868. debug(F101,"http_open FIONBIO","",x);
  9869. #endif /* NON_BLOCK_IO */
  9870. /* We have succeeded in connecting to the HTTP PROXY. So now we */
  9871. /* need to attempt to connect through the proxy to the actual host */
  9872. /* If that is successful, we have to pretend that we made a direct */
  9873. /* connection to the actual host. */
  9874. if ( tcp_http_proxy ) {
  9875. #ifdef OS2
  9876. if (!agent)
  9877. agent = "Kermit 95"; /* Default user agent */
  9878. #else
  9879. if (!agent)
  9880. agent = "C-Kermit";
  9881. #endif /* OS2 */
  9882. if (http_connect(httpfd,
  9883. tcp_http_proxy_agent ? tcp_http_proxy_agent : agent,
  9884. NULL,
  9885. tcp_http_proxy_user,
  9886. tcp_http_proxy_pwd,
  9887. 0,
  9888. proxycopy
  9889. ) < 0) {
  9890. http_close();
  9891. return(-1);
  9892. }
  9893. }
  9894. #ifdef SO_OOBINLINE
  9895. /* See note on SO_OOBINLINE in netopen() */
  9896. #ifdef datageneral
  9897. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9898. #else
  9899. #ifdef BSD43
  9900. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9901. #else
  9902. #ifdef OSF1
  9903. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9904. #else
  9905. #ifdef POSIX
  9906. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9907. #else
  9908. #ifdef MOTSV88R4
  9909. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9910. #else
  9911. #ifdef SOLARIS
  9912. /*
  9913. Maybe this applies to all SVR4 versions, but the other (else) way has been
  9914. compiling and working fine on all the others, so best not to change it.
  9915. */
  9916. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9917. #else
  9918. #ifdef OSK
  9919. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9920. #else
  9921. #ifdef OS2
  9922. {
  9923. int rc;
  9924. rc = setsockopt(httpfd,
  9925. SOL_SOCKET,
  9926. SO_OOBINLINE,
  9927. (char *) &on,
  9928. sizeof on
  9929. );
  9930. debug(F111,"setsockopt SO_OOBINLINE",on ? "on" : "off" ,rc);
  9931. }
  9932. #else
  9933. #ifdef VMS /* or, at least, VMS with gcc */
  9934. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9935. #else
  9936. #ifdef CLIX
  9937. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
  9938. #else
  9939. setsockopt(httpfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
  9940. #endif /* CLIX */
  9941. #endif /* VMS */
  9942. #endif /* OS2 */
  9943. #endif /* OSK */
  9944. #endif /* SOLARIS */
  9945. #endif /* MOTSV88R4 */
  9946. #endif /* POSIX */
  9947. #endif /* BSD43 */
  9948. #endif /* OSF1 */
  9949. #endif /* datageneral */
  9950. #endif /* SO_OOBINLINE */
  9951. #ifndef NOTCPOPTS
  9952. #ifndef datageneral
  9953. #ifdef SOL_SOCKET
  9954. #ifdef TCP_NODELAY
  9955. no_delay(ttyfd,tcp_nodelay);
  9956. #endif /* TCP_NODELAY */
  9957. #ifdef SO_KEEPALIVE
  9958. keepalive(ttyfd,tcp_keepalive);
  9959. #endif /* SO_KEEPALIVE */
  9960. #ifdef SO_LINGER
  9961. ck_linger(ttyfd,tcp_linger, tcp_linger_tmo);
  9962. #endif /* SO_LINGER */
  9963. #ifdef SO_SNDBUF
  9964. sendbuf(ttyfd,tcp_sendbuf);
  9965. #endif /* SO_SNDBUF */
  9966. #ifdef SO_RCVBUF
  9967. recvbuf(ttyfd,tcp_recvbuf);
  9968. #endif /* SO_RCVBUF */
  9969. #endif /* SOL_SOCKET */
  9970. #endif /* datageneral */
  9971. #endif /* NOTCPOPTS */
  9972. #ifndef datageneral
  9973. /* Find out our own IP address. */
  9974. /* We need the l_addr structure for [E]KLOGIN. */
  9975. l_slen = sizeof(l_addr);
  9976. bzero((char *)&l_addr, l_slen);
  9977. #ifndef EXCELAN
  9978. if (!getsockname(httpfd, (struct sockaddr *)&l_addr, &l_slen)) {
  9979. char * s = (char *)inet_ntoa(l_addr.sin_addr);
  9980. ckstrncpy(myipaddr, s, 20);
  9981. debug(F110,"getsockname",myipaddr,0);
  9982. }
  9983. #endif /* EXCELAN */
  9984. #endif /* datageneral */
  9985. /* See note in netopen() on Reverse DNS lookups */
  9986. if (tcp_rdns == SET_ON) {
  9987. #ifdef NT
  9988. if (isWin95())
  9989. sleep(1);
  9990. #endif /* NT */
  9991. if (!quiet) {
  9992. printf(" Reverse DNS Lookup... ");
  9993. fflush(stdout);
  9994. }
  9995. if (host = gethostbyaddr((char *)&r_addr.sin_addr,4,PF_INET)) {
  9996. char * s;
  9997. host = ck_copyhostent(host);
  9998. debug(F100,"http_open gethostbyname != NULL","",0);
  9999. if (!quiet) {
  10000. printf("(OK)\n");
  10001. fflush(stdout);
  10002. }
  10003. s = host->h_name;
  10004. if (!s) { /* This can happen... */
  10005. debug(F100,"http_open host->h_name is NULL","",0);
  10006. s = "";
  10007. }
  10008. /* Something is wrong with inet_ntoa() on HPUX 10.xx */
  10009. /* The compiler says "Integral value implicitly converted to */
  10010. /* pointer in assignment." The prototype is right there */
  10011. /* in <arpa/inet.h> so what's the problem? */
  10012. /* Ditto in HP-UX 5.x, but not 8.x or 9.x... */
  10013. if (!*s) { /* No name so substitute the address */
  10014. debug(F100,"http_open host->h_name is empty","",0);
  10015. s = inet_ntoa(r_addr.sin_addr); /* Convert address to string */
  10016. if (!s) /* Trust No 1 */
  10017. s = "";
  10018. if (*s) { /* If it worked, use this string */
  10019. ckstrncpy(http_ip,s,20);
  10020. }
  10021. s = http_ip; /* Otherwise stick with the IP */
  10022. if (!*s) /* or failing that */
  10023. s = http_host_port; /* the name we were called with. */
  10024. }
  10025. if (*s) /* return the rdns name */
  10026. ckmakmsg(rdns_name,rdns_len,s,":",svcname,NULL);
  10027. if (!quiet && *s
  10028. #ifndef NOICP
  10029. && !doconx
  10030. #endif /* NOICP */
  10031. ) {
  10032. printf(" %s connected on port %s\n",s,
  10033. ckuitoa(ntohs(service->s_port)));
  10034. #ifdef BETADEBUG
  10035. /* This is simply for testing the DNS entries */
  10036. if (host->h_aliases) {
  10037. char ** a = host->h_aliases;
  10038. while (*a) {
  10039. printf(" alias => %s\n",*a);
  10040. a++;
  10041. }
  10042. }
  10043. #endif /* BETADEBUG */
  10044. }
  10045. } else {
  10046. if (!quiet) printf("Failed.\n");
  10047. }
  10048. } else if (!quiet) printf("(OK)\n");
  10049. if (!quiet) fflush(stdout);
  10050. if ( tcp_http_proxy ) {
  10051. /* Erase the IP address since we cannot reuse it */
  10052. http_ip[0] = '\0';
  10053. } else {
  10054. /* This should already have been done but just in case */
  10055. ckstrncpy(http_ip,(char *)inet_ntoa(r_addr.sin_addr),20);
  10056. }
  10057. makestr(&http_agent,agent);
  10058. #ifdef CK_SSL
  10059. if (use_ssl && ck_ssleay_is_installed()) {
  10060. if (!ssl_http_init(hostname)) {
  10061. if (bio_err!=NULL) {
  10062. BIO_printf(bio_err,"ssl_tn_init() failed\n");
  10063. ERR_print_errors(bio_err);
  10064. } else {
  10065. fflush(stderr);
  10066. fprintf(stderr,"ssl_tn_init() failed\n");
  10067. ERR_print_errors_fp(stderr);
  10068. }
  10069. http_close();
  10070. return(-1);
  10071. } else if ( ck_ssl_http_client(httpfd,hostname) < 0 ) {
  10072. http_close();
  10073. return(-1);
  10074. }
  10075. }
  10076. #endif /* CK_SSL */
  10077. #endif /* TCPSOCKET */
  10078. return(0); /* Done. */
  10079. }
  10080. int
  10081. #ifdef CK_ANSIC
  10082. http_close(VOID)
  10083. #else /* CK_ANSIC */
  10084. http_close()
  10085. #endif /* CK_ANSIC */
  10086. {
  10087. int x = 0;
  10088. debug(F101,"http_close","",httpfd);
  10089. #ifdef HTTP_BUFFERING
  10090. http_count = 0;
  10091. http_bufp = 0;
  10092. #endif /* HTTP_BUFFERING */
  10093. if (httpfd == -1) /* Was open? */
  10094. return(0); /* Wasn't. */
  10095. #ifndef OS2
  10096. if (httpfd > -1) /* Was. */
  10097. #endif /* OS2 */
  10098. {
  10099. #ifdef CK_SSL
  10100. if (tls_http_active_flag) {
  10101. if (ssl_debug_flag)
  10102. BIO_printf(bio_err,"calling SSL_shutdown\n");
  10103. SSL_shutdown(tls_http_con);
  10104. tls_http_active_flag = 0;
  10105. }
  10106. #endif /* CK_SSL */
  10107. #ifdef TCPIPLIB
  10108. x = socket_close(httpfd); /* Close it. */
  10109. #else
  10110. #ifndef OS2
  10111. x = close(httpfd);
  10112. #endif /* OS2 */
  10113. #endif /* TCPIPLIB */
  10114. }
  10115. httpfd = -1; /* Mark it as closed. */
  10116. /* do not erase http_host_port, http_ip, http_port so they */
  10117. /* can be used by http_reopen() */
  10118. return(x);
  10119. }
  10120. /* http_tol()
  10121. * Call with s = pointer to string, n = length.
  10122. * Returns number of bytes actually written on success, or
  10123. * -1 on i/o error, -2 if called improperly.
  10124. */
  10125. int
  10126. http_tol(s,n) CHAR *s; int n; {
  10127. int count = 0;
  10128. int len = n;
  10129. int try = 0;
  10130. if (httpfd == -1) {
  10131. debug(F100,"http_tol socket is closed","",0);
  10132. return -1;
  10133. }
  10134. debug(F101,"http_tol TCPIPLIB ttnet","",ttnet);
  10135. #ifdef COMMENT
  10136. ckhexdump("http_tol",s,n);
  10137. #endif /* COMMENT */
  10138. #ifdef CK_SSL
  10139. if (tls_http_active_flag) {
  10140. int error, r;
  10141. /* Write using SSL */
  10142. ssl_retry:
  10143. r = SSL_write(tls_http_con, s, len /* >1024?1024:len */);
  10144. switch (SSL_get_error(tls_http_con,r)) {
  10145. case SSL_ERROR_NONE:
  10146. debug(F111,"http_tol","SSL_write",r);
  10147. if ( r == len )
  10148. return(n);
  10149. s += r;
  10150. len -= r;
  10151. goto ssl_retry;
  10152. case SSL_ERROR_WANT_WRITE:
  10153. debug(F100,"http_tol SSL_ERROR_WANT_WRITE","",0);
  10154. return(-1);
  10155. case SSL_ERROR_WANT_READ:
  10156. debug(F100,"http_tol SSL_ERROR_WANT_READ","",0);
  10157. return(-1);
  10158. case SSL_ERROR_SYSCALL:
  10159. if ( r == 0 ) { /* EOF */
  10160. http_close();
  10161. return(-2);
  10162. } else {
  10163. int rc = -1;
  10164. #ifdef NT
  10165. int gle = GetLastError();
  10166. debug(F111,"http_tol SSL_ERROR_SYSCALL",
  10167. "GetLastError()",gle);
  10168. rc = os2socketerror(gle);
  10169. if (rc == -1)
  10170. rc = -2;
  10171. else if ( rc == -2 )
  10172. return -1;
  10173. #endif /* NT */
  10174. return(rc);
  10175. }
  10176. case SSL_ERROR_WANT_X509_LOOKUP:
  10177. debug(F100,"http_tol SSL_ERROR_WANT_X509_LOOKUP","",0);
  10178. http_close();
  10179. return(-2);
  10180. case SSL_ERROR_SSL:
  10181. debug(F100,"http_tol SSL_ERROR_SSL","",0);
  10182. http_close();
  10183. return(-2);
  10184. case SSL_ERROR_ZERO_RETURN:
  10185. debug(F100,"http_tol SSL_ERROR_ZERO_RETURN","",0);
  10186. http_close();
  10187. return(-2);
  10188. default:
  10189. debug(F100,"http_tol SSL_ERROR_?????","",0);
  10190. http_close();
  10191. return(-2);
  10192. }
  10193. }
  10194. #endif /* CK_SSL */
  10195. http_tol_retry:
  10196. try++; /* Increase the try counter */
  10197. {
  10198. #ifdef BSDSELECT
  10199. fd_set wfds;
  10200. struct timeval tv;
  10201. debug(F101,"http_tol BSDSELECT","",0);
  10202. tv.tv_usec = 0L;
  10203. tv.tv_sec=30;
  10204. #ifdef NT
  10205. WSASafeToCancel = 1;
  10206. #endif /* NT */
  10207. #ifdef STREAMING
  10208. do_select:
  10209. #endif /* STREAMING */
  10210. FD_ZERO(&wfds);
  10211. FD_SET(httpfd, &wfds);
  10212. if (select(FD_SETSIZE, NULL,
  10213. #ifdef __DECC
  10214. #ifndef __DECC_VER
  10215. (int *)
  10216. #endif /* __DECC_VER */
  10217. #endif /* __DECC */
  10218. &wfds, NULL, &tv) < 0) {
  10219. int s_errno = socket_errno;
  10220. debug(F101,"http_tol select failed","",s_errno);
  10221. #ifdef BETADEBUG
  10222. printf("http_tol select failed: %d\n", s_errno);
  10223. #endif /* BETADEBUG */
  10224. #ifdef NT
  10225. WSASafeToCancel = 0;
  10226. if (!win95selectbug)
  10227. #endif /* NT */
  10228. return(-1);
  10229. }
  10230. if (!FD_ISSET(httpfd, &wfds)) {
  10231. #ifdef STREAMING
  10232. if (streaming)
  10233. goto do_select;
  10234. #endif /* STREAMING */
  10235. debug(F111,"http_tol","!FD_ISSET",ttyfd);
  10236. #ifdef NT
  10237. WSASafeToCancel = 0;
  10238. if (!win95selectbug)
  10239. #endif /* NT */
  10240. return(-1);
  10241. }
  10242. #ifdef NT
  10243. WSASafeToCancel = 0;
  10244. #endif /* NT */
  10245. #else /* BSDSELECT */
  10246. #ifdef IBMSELECT
  10247. {
  10248. int tries = 0;
  10249. debug(F101,"http_tol IBMSELECT","",0);
  10250. while (select(&httpfd, 0, 1, 0, 1000) != 1) {
  10251. int count;
  10252. if (tries++ >= 60) {
  10253. /* if after 60 seconds we can't get permission to write */
  10254. debug(F101,"http_tol select failed","",socket_errno);
  10255. return(-1);
  10256. }
  10257. #ifdef COMMENT
  10258. if ((count = http_tchk()) < 0) {
  10259. debug(F111,"http_tol","http_tchk()",count);
  10260. return(count);
  10261. }
  10262. #endif /* COMMENT */
  10263. }
  10264. }
  10265. #endif /* IBMSELECT */
  10266. #endif /* BSDSELECT */
  10267. #ifdef TCPIPLIB
  10268. if ((count = socket_write(httpfd,s,n)) < 0) {
  10269. int s_errno = socket_errno; /* maybe a function */
  10270. debug(F101,"http_tol socket_write error","",s_errno);
  10271. #ifdef OS2
  10272. if (os2socketerror(s_errno) < 0)
  10273. return(-2);
  10274. #endif /* OS2 */
  10275. return(-1); /* Call it an i/o error */
  10276. }
  10277. #else /* TCPIPLIB */
  10278. if ((count = write(httpfd,s,n)) < 0) {
  10279. debug(F101,"http_tol socket_write error","",errno);
  10280. return(-1); /* Call it an i/o error */
  10281. }
  10282. #endif /* TCPIPLIB */
  10283. if (count < n) {
  10284. debug(F111,"http_tol socket_write",s,count);
  10285. if (try > 25) {
  10286. /* don't try more than 25 times */
  10287. debug(F100,"http_tol tried more than 25 times","",0);
  10288. return(-1);
  10289. }
  10290. if (count > 0) {
  10291. s += count;
  10292. n -= count;
  10293. }
  10294. debug(F111,"http_tol retry",s,n);
  10295. goto http_tol_retry;
  10296. } else {
  10297. debug(F111,"http_tol socket_write",s,count);
  10298. return(len); /* success - return total length */
  10299. }
  10300. }
  10301. }
  10302. int
  10303. http_inc(timo) int timo; {
  10304. int x=-1; unsigned char c; /* The locals. */
  10305. if (httpfd == -1) {
  10306. #ifdef HTTP_BUFFERING
  10307. http_count = 0;
  10308. http_bufp = 0;
  10309. #endif /* HTTP_BUFFERING */
  10310. debug(F100,"http_inc socket is closed","",0);
  10311. return(-2);
  10312. }
  10313. #ifdef CK_SSL
  10314. /*
  10315. * In the case of OpenSSL, it is possible that there is still
  10316. * data waiting in the SSL session buffers that has not yet
  10317. * been read by Kermit. If this is the case we must process
  10318. * it without calling select() because select() will not return
  10319. * with an indication that there is data to be read from the
  10320. * socket. If there is no data pending in the SSL session
  10321. * buffers then fall through to the select() code and wait for
  10322. * some data to arrive.
  10323. */
  10324. if (tls_http_active_flag) {
  10325. int error;
  10326. x = SSL_pending(tls_http_con);
  10327. if (x < 0) {
  10328. debug(F111,"http_inc","SSL_pending error",x);
  10329. http_close();
  10330. return(-1);
  10331. } else if ( x > 0 ) {
  10332. ssl_read:
  10333. x = SSL_read(tls_http_con, &c, 1);
  10334. error = SSL_get_error(tls_http_con,x);
  10335. switch (error) {
  10336. case SSL_ERROR_NONE:
  10337. debug(F111,"http_inc SSL_ERROR_NONE","x",x);
  10338. if (x > 0) {
  10339. #ifdef OS2
  10340. ReleaseTCPIPMutex();
  10341. #endif /* OS2 */
  10342. return(c); /* Return character. */
  10343. } else if (x < 0) {
  10344. #ifdef OS2
  10345. ReleaseTCPIPMutex();
  10346. #endif /* OS2 */
  10347. return(-1);
  10348. } else {
  10349. http_close();
  10350. #ifdef OS2
  10351. ReleaseTCPIPMutex();
  10352. #endif /* OS2 */
  10353. return(-2);
  10354. }
  10355. case SSL_ERROR_WANT_WRITE:
  10356. debug(F100,"http_inc SSL_ERROR_WANT_WRITE","",0);
  10357. #ifdef OS2
  10358. ReleaseTCPIPMutex();
  10359. #endif /* OS2 */
  10360. return(-1);
  10361. case SSL_ERROR_WANT_READ:
  10362. debug(F100,"http_inc SSL_ERROR_WANT_READ","",0);
  10363. #ifdef OS2
  10364. ReleaseTCPIPMutex();
  10365. #endif /* OS2 */
  10366. return(-1);
  10367. case SSL_ERROR_SYSCALL:
  10368. if ( x == 0 ) { /* EOF */
  10369. http_close();
  10370. #ifdef OS2
  10371. ReleaseTCPIPMutex();
  10372. #endif /* OS2 */
  10373. return(-2);
  10374. } else {
  10375. int rc = -1;
  10376. #ifdef NT
  10377. int gle = GetLastError();
  10378. debug(F111,"http_inc SSL_ERROR_SYSCALL",
  10379. "GetLastError()",gle);
  10380. rc = os2socketerror(gle);
  10381. if (rc == -1)
  10382. rc = -2;
  10383. else if ( rc == -2 )
  10384. rc = -1;
  10385. #endif /* NT */
  10386. #ifdef OS2
  10387. ReleaseTCPIPMutex();
  10388. #endif /* OS2 */
  10389. return(rc);
  10390. }
  10391. case SSL_ERROR_WANT_X509_LOOKUP:
  10392. debug(F100,"http_inc SSL_ERROR_WANT_X509_LOOKUP","",0);
  10393. http_close();
  10394. #ifdef OS2
  10395. ReleaseTCPIPMutex();
  10396. #endif /* OS2 */
  10397. return(-2);
  10398. case SSL_ERROR_SSL:
  10399. debug(F100,"http_inc SSL_ERROR_SSL","",0);
  10400. #ifdef COMMENT
  10401. http_close();
  10402. #endif /* COMMENT */
  10403. #ifdef OS2
  10404. ReleaseTCPIPMutex();
  10405. #endif /* OS2 */
  10406. return(-2);
  10407. case SSL_ERROR_ZERO_RETURN:
  10408. debug(F100,"http_inc SSL_ERROR_ZERO_RETURN","",0);
  10409. http_close();
  10410. #ifdef OS2
  10411. ReleaseTCPIPMutex();
  10412. #endif /* OS2 */
  10413. return(-2);
  10414. default:
  10415. debug(F100,"http_inc SSL_ERROR_?????","",0);
  10416. http_close();
  10417. #ifdef OS2
  10418. ReleaseTCPIPMutex();
  10419. #endif /* OS2 */
  10420. return(-2);
  10421. }
  10422. }
  10423. }
  10424. #endif /* CK_SSL */
  10425. #ifdef HTTP_BUFFERING
  10426. /* Skip all the select() stuff if we have bytes buffered locally */
  10427. if (http_count > 0)
  10428. goto getfrombuffer;
  10429. #endif /* HTTP_BUFFERING */
  10430. {
  10431. #ifdef BSDSELECT
  10432. fd_set rfds;
  10433. struct timeval tv;
  10434. int timeout = timo < 0 ? -timo : 1000 * timo;
  10435. debug(F101,"http_inc BSDSELECT","",timo);
  10436. for ( ; timeout >= 0; timeout -= (timo ? 100 : 0)) {
  10437. int rc;
  10438. debug(F111,"http_inc","timeout",timeout);
  10439. /* Don't move select() initialization out of the loop. */
  10440. FD_ZERO(&rfds);
  10441. FD_SET(httpfd, &rfds);
  10442. tv.tv_sec = tv.tv_usec = 0L;
  10443. if (timo)
  10444. tv.tv_usec = (long) 100000L;
  10445. else
  10446. tv.tv_sec = 30;
  10447. #ifdef NT
  10448. WSASafeToCancel = 1;
  10449. #endif /* NT */
  10450. rc = select(FD_SETSIZE,
  10451. #ifndef __DECC
  10452. (fd_set *)
  10453. #endif /* __DECC */
  10454. &rfds, NULL, NULL, &tv);
  10455. if (rc < 0) {
  10456. int s_errno = socket_errno;
  10457. debug(F111,"http_inc","select",rc);
  10458. debug(F111,"http_inc","socket_errno",s_errno);
  10459. #ifdef HTTP_BUFFERING
  10460. http_count = 0;
  10461. http_bufp = 0;
  10462. #endif /* HTTP_BUFFERING */
  10463. if (s_errno)
  10464. return(-1);
  10465. }
  10466. debug(F111,"http_inc","select",rc);
  10467. #ifdef NT
  10468. WSASafeToCancel = 0;
  10469. #endif /* NT */
  10470. if (FD_ISSET(httpfd, &rfds)) {
  10471. x = 0;
  10472. break;
  10473. } else {
  10474. /* If waiting forever we have no way of knowing if the */
  10475. /* socket closed so try writing a 0-length TCP packet */
  10476. /* which should force an error if the socket is closed */
  10477. if (!timo) {
  10478. #ifdef TCPIPLIB
  10479. if ((rc = socket_write(httpfd,"",0)) < 0) {
  10480. #ifdef HTTP_BUFFERING
  10481. http_count = 0;
  10482. http_bufp = 0;
  10483. #endif /* HTTP_BUFFERING */
  10484. int s_errno = socket_errno;
  10485. debug(F101,"http_inc socket_write error","",s_errno);
  10486. #ifdef OS2
  10487. if (os2socketerror(s_errno) < 0)
  10488. return(-2);
  10489. #endif /* OS2 */
  10490. return(-1); /* Call it an i/o error */
  10491. }
  10492. #else /* TCPIPLIB */
  10493. if ((rc = write(httpfd,"",0)) < 0) {
  10494. #ifdef HTTP_BUFFERING
  10495. http_count = 0;
  10496. http_bufp = 0;
  10497. #endif /* HTTP_BUFFERING */
  10498. debug(F101,"http_inc socket_write error","",errno);
  10499. return(-1); /* Call it an i/o error */
  10500. }
  10501. #endif /* TCPIPLIB */
  10502. }
  10503. continue;
  10504. }
  10505. }
  10506. #ifdef NT
  10507. WSASafeToCancel = 0;
  10508. #endif /* NT */
  10509. #else /* !BSDSELECT */
  10510. #ifdef IBMSELECT
  10511. /*
  10512. Was used by OS/2, currently not used, but might come in handy some day...
  10513. ... and it came in handy! For our TCP/IP layer, it avoids all the fd_set
  10514. and timeval stuff since this is the only place where it is used.
  10515. */
  10516. int socket = httpfd;
  10517. int timeout = timo < 0 ? -timo : 1000 * timo;
  10518. debug(F101,"http_inc IBMSELECT","",timo);
  10519. for ( ; timeout >= 0; timeout -= (timo ? 100 : 0)) {
  10520. if (select(&socket, 1, 0, 0, 100L) == 1) {
  10521. x = 0;
  10522. break;
  10523. }
  10524. }
  10525. #else /* !IBMSELECT */
  10526. SELECT is required for this code
  10527. #endif /* IBMSELECT */
  10528. #endif /* BSDSELECT */
  10529. }
  10530. if (timo && x < 0) { /* select() timed out */
  10531. #ifdef HTTP_BUFFERING
  10532. http_count = 0;
  10533. http_bufp = 0;
  10534. #endif /* HTTP_BUFFERING */
  10535. debug(F100,"http_inc select() timed out","",0);
  10536. return(-1); /* Call it an i/o error */
  10537. }
  10538. #ifdef CK_SSL
  10539. if ( tls_http_active_flag ) {
  10540. int error;
  10541. ssl_read2:
  10542. x = SSL_read(tls_http_con, &c, 1);
  10543. error = SSL_get_error(tls_http_con,x);
  10544. switch (error) {
  10545. case SSL_ERROR_NONE:
  10546. debug(F111,"http_inc SSL_ERROR_NONE","x",x);
  10547. if (x > 0) {
  10548. #ifdef OS2
  10549. ReleaseTCPIPMutex();
  10550. #endif /* OS2 */
  10551. return(c); /* Return character. */
  10552. } else if (x < 0) {
  10553. #ifdef OS2
  10554. ReleaseTCPIPMutex();
  10555. #endif /* OS2 */
  10556. return(-1);
  10557. } else {
  10558. http_close();
  10559. #ifdef OS2
  10560. ReleaseTCPIPMutex();
  10561. #endif /* OS2 */
  10562. return(-2);
  10563. }
  10564. case SSL_ERROR_WANT_WRITE:
  10565. debug(F100,"http_inc SSL_ERROR_WANT_WRITE","",0);
  10566. #ifdef OS2
  10567. ReleaseTCPIPMutex();
  10568. #endif /* OS2 */
  10569. return(-1);
  10570. case SSL_ERROR_WANT_READ:
  10571. debug(F100,"http_inc SSL_ERROR_WANT_READ","",0);
  10572. #ifdef OS2
  10573. ReleaseTCPIPMutex();
  10574. #endif /* OS2 */
  10575. return(-1);
  10576. case SSL_ERROR_SYSCALL:
  10577. if ( x == 0 ) { /* EOF */
  10578. http_close();
  10579. #ifdef OS2
  10580. ReleaseTCPIPMutex();
  10581. #endif /* OS2 */
  10582. return(-2);
  10583. } else {
  10584. int rc = -1;
  10585. #ifdef NT
  10586. int gle = GetLastError();
  10587. debug(F111,"http_inc SSL_ERROR_SYSCALL",
  10588. "GetLastError()",gle);
  10589. rc = os2socketerror(gle);
  10590. if (rc == -1)
  10591. rc = -2;
  10592. else if ( rc == -2 )
  10593. rc = -1;
  10594. #endif /* NT */
  10595. #ifdef OS2
  10596. ReleaseTCPIPMutex();
  10597. #endif /* OS2 */
  10598. return(rc);
  10599. }
  10600. case SSL_ERROR_WANT_X509_LOOKUP:
  10601. debug(F100,"http_inc SSL_ERROR_WANT_X509_LOOKUP","",0);
  10602. http_close();
  10603. #ifdef OS2
  10604. ReleaseTCPIPMutex();
  10605. #endif /* OS2 */
  10606. return(-2);
  10607. case SSL_ERROR_SSL:
  10608. debug(F100,"http_inc SSL_ERROR_SSL","",0);
  10609. #ifdef COMMENT
  10610. http_close();
  10611. #endif /* COMMENT */
  10612. #ifdef OS2
  10613. ReleaseTCPIPMutex();
  10614. #endif /* OS2 */
  10615. return(-2);
  10616. case SSL_ERROR_ZERO_RETURN:
  10617. debug(F100,"http_inc SSL_ERROR_ZERO_RETURN","",0);
  10618. http_close();
  10619. #ifdef OS2
  10620. ReleaseTCPIPMutex();
  10621. #endif /* OS2 */
  10622. return(-2);
  10623. default:
  10624. debug(F100,"http_inc SSL_ERROR_?????","",0);
  10625. http_close();
  10626. #ifdef OS2
  10627. ReleaseTCPIPMutex();
  10628. #endif /* OS2 */
  10629. return(-2);
  10630. }
  10631. }
  10632. #endif /* CK_SSL */
  10633. #ifdef HTTP_BUFFERING
  10634. /*
  10635. Buffering code added by fdc 15 Dec 2005 for non-SSL case only because HTTP
  10636. GETs were orders of magnitude too slow due to the single-byte read()s. The
  10637. file-descriptor swapping is pretty gross, but the more elegant solution
  10638. (calling a nettchk() like routine with the fd as a parameter) doesn't work,
  10639. because nettchk() relies on too many other routines that, like itself, are
  10640. hardwired for ttyfd.
  10641. */
  10642. getfrombuffer:
  10643. if (--http_count >= 0) {
  10644. c = http_inbuf[http_bufp++];
  10645. x = 1;
  10646. } else {
  10647. int savefd;
  10648. savefd = ttyfd;
  10649. ttyfd = httpfd;
  10650. x = nettchk();
  10651. ttyfd = savefd;
  10652. debug(F101,"http_inc nettchk","",x);
  10653. if (x > HTTP_INBUFLEN)
  10654. x = HTTP_INBUFLEN;
  10655. #ifdef TCPIPLIB
  10656. x = socket_read(httpfd,http_inbuf,x);
  10657. #else /* Not TCPIPLIB */
  10658. x = read(httpfd,http_inbuf,x);
  10659. #endif /* TCPIPLIB */
  10660. http_count = 0;
  10661. http_bufp = 0;
  10662. if (x > 0) {
  10663. c = http_inbuf[http_bufp++];
  10664. http_count = x - 1;
  10665. }
  10666. }
  10667. #else /* Not HTTP_BUFFERING */
  10668. #ifdef TCPIPLIB
  10669. x = socket_read(httpfd,&c,1);
  10670. #else /* Not TCPIPLIB */
  10671. x = read(httpfd,&c,1);
  10672. #endif /* TCPIPLIB */
  10673. #endif /* HTTP_BUFFERING */
  10674. if (x <= 0) {
  10675. int s_errno = socket_errno;
  10676. debug(F101,"ttbufr socket_read","",x);
  10677. debug(F101,"ttbufr socket_errno","",s_errno);
  10678. #ifdef OS2
  10679. if (x == 0 || os2socketerror(s_errno) < 0) {
  10680. http_close();
  10681. ReleaseTCPIPMutex();
  10682. return(-2);
  10683. }
  10684. ReleaseTCPIPMutex();
  10685. return(-1);
  10686. #else /* OS2 */
  10687. http_close(); /* *** *** */
  10688. return(-2);
  10689. #endif /* OS2 */
  10690. }
  10691. return(c);
  10692. }
  10693. void
  10694. #ifdef CK_ANSIC
  10695. http_set_code_reply(char * msg)
  10696. #else
  10697. http_set_code_reply(msg)
  10698. char * msg;
  10699. #endif /* CK_ANSIC */
  10700. {
  10701. char * p = msg;
  10702. char buf[16];
  10703. int i=0;
  10704. while ( *p != SP && *p != NUL ) {
  10705. buf[i] = *p;
  10706. p++;
  10707. i++;
  10708. }
  10709. http_code = atoi(buf);
  10710. while ( *p == SP )
  10711. p++;
  10712. ckstrncpy(http_reply_str,p,HTTPBUFLEN);
  10713. }
  10714. int
  10715. #ifdef CK_ANSIC
  10716. http_get(char * agent, char ** hdrlist, char * user,
  10717. char * pwd, char array, char * local, char * remote,
  10718. int stdio)
  10719. #else
  10720. http_get(agent, hdrlist, user, pwd, array, local, remote, stdio)
  10721. char * agent; char ** hdrlist; char * user;
  10722. char * pwd; char array; char * local; char * remote;
  10723. int stdio;
  10724. #endif /* CK_ANSIC */
  10725. {
  10726. char * request = NULL;
  10727. int i, j, len = 0, hdcnt = 0, rc = 0;
  10728. int ch;
  10729. int http_fnd = 0;
  10730. char buf[HTTPBUFLEN], *p;
  10731. int nullline;
  10732. #ifdef OS2
  10733. struct utimbuf u_t;
  10734. #else /* OS2 */
  10735. #ifdef SYSUTIMEH
  10736. struct utimbuf u_t;
  10737. #else
  10738. struct utimbuf {
  10739. time_t atime;
  10740. time_t mtime;
  10741. } u_t;
  10742. #endif /* SYSUTIMH */
  10743. #endif /* OS2 */
  10744. time_t mod_t = 0;
  10745. time_t srv_t = 0;
  10746. time_t local_t = 0;
  10747. char passwd[64];
  10748. char b64in[128];
  10749. char b64out[256];
  10750. char * headers[HTTPHEADCNT];
  10751. int closecon = 0;
  10752. int chunked = 0;
  10753. int zfile = 0;
  10754. int first = 1;
  10755. #ifdef DEBUG
  10756. if (deblog) {
  10757. debug(F101,"http_get httpfd","",httpfd);
  10758. debug(F110,"http_agent",agent,0);
  10759. debug(F110,"http_user",user,0);
  10760. debug(F110,"http_local",local,0);
  10761. debug(F110,"http_remote",remote,0);
  10762. }
  10763. #endif /* DEBUG */
  10764. if (!remote) remote = "";
  10765. if (httpfd == -1)
  10766. return(-1);
  10767. if (array) {
  10768. for (i = 0; i < HTTPHEADCNT; i++)
  10769. headers[i] = NULL;
  10770. }
  10771. len = 8; /* GET */
  10772. len += strlen(HTTP_VERSION);
  10773. len += strlen(remote);
  10774. len += 16;
  10775. if (hdrlist) {
  10776. for (i = 0; hdrlist[i]; i++)
  10777. len += strlen(hdrlist[i]) + 2;
  10778. }
  10779. len += (int) strlen(http_host_port) + 8;
  10780. if (agent)
  10781. len += 13 + strlen(agent);
  10782. if (user) {
  10783. if (!pwd) {
  10784. readpass("Password: ",passwd,64);
  10785. pwd = passwd;
  10786. }
  10787. ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
  10788. j = b8tob64(b64in,strlen(b64in),b64out,256);
  10789. memset(pwd,0,strlen(pwd)); /* NOT PORTABLE */
  10790. if (j < 0)
  10791. return(-1);
  10792. b64out[j] = '\0';
  10793. len += j + 24;
  10794. }
  10795. #ifdef HTTP_CLOSE
  10796. len += 19; /* Connection: close */
  10797. #endif
  10798. len += 3; /* blank line + null */
  10799. request = malloc(len);
  10800. if (!request)
  10801. return(-1);
  10802. sprintf(request,"GET %s %s\r\n",remote,HTTP_VERSION); /* safe */
  10803. ckstrncat(request,"Host: ", len);
  10804. ckstrncat(request,http_host_port, len);
  10805. ckstrncat(request,"\r\n",len);
  10806. if (agent) {
  10807. ckstrncat(request,"User-agent: ",len);
  10808. ckstrncat(request,agent,len);
  10809. ckstrncat(request,"\r\n",len);
  10810. }
  10811. if (user) {
  10812. ckstrncat(request,"Authorization: Basic ",len);
  10813. ckstrncat(request,b64out,len);
  10814. ckstrncat(request,"\r\n",len);
  10815. }
  10816. if ( hdrlist ) {
  10817. for (i = 0; hdrlist[i]; i++) {
  10818. ckstrncat(request,hdrlist[i],len);
  10819. ckstrncat(request,"\r\n",len);
  10820. }
  10821. }
  10822. #ifdef HTTP_CLOSE
  10823. ckstrncat(request,"Connection: close\r\n",len);
  10824. #endif
  10825. ckstrncat(request,"\r\n",len);
  10826. getreq:
  10827. if (http_tol((CHAR *)request,strlen(request)) < 0)
  10828. {
  10829. http_close();
  10830. if ( first ) {
  10831. first--;
  10832. http_reopen();
  10833. goto getreq;
  10834. }
  10835. rc = -1;
  10836. goto getexit;
  10837. }
  10838. /* Process the headers */
  10839. local_t = time(NULL);
  10840. nullline = 0;
  10841. i = 0;
  10842. len = -1;
  10843. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  10844. buf[i] = ch;
  10845. if ( buf[i] == 10 ) { /* found end of line */
  10846. if (i > 0 && buf[i-1] == 13)
  10847. i--;
  10848. if (i < 1)
  10849. nullline = 1;
  10850. buf[i] = '\0';
  10851. if (array && !nullline && hdcnt < HTTPHEADCNT)
  10852. makestr(&headers[hdcnt++],buf);
  10853. if (!ckstrcmp(buf,"HTTP",4,0)) {
  10854. http_fnd = 1;
  10855. j = ckindex(" ",buf,0,0,0);
  10856. p = &buf[j];
  10857. while ( isspace(*p) )
  10858. p++;
  10859. switch ( p[0] ) {
  10860. case '1': /* Informational message */
  10861. break;
  10862. case '2': /* Success */
  10863. break;
  10864. case '3': /* Redirection */
  10865. case '4': /* Client failure */
  10866. case '5': /* Server failure */
  10867. default: /* Unknown */
  10868. if (!quiet)
  10869. printf("Failure: Server reports %s\n",p);
  10870. rc = -1;
  10871. local = NULL;
  10872. }
  10873. http_set_code_reply(p);
  10874. #ifdef CMDATE2TM
  10875. } else if (!ckstrcmp(buf,"Last-Modified",13,0)) {
  10876. mod_t = http_date(&buf[15]);
  10877. } else if (!ckstrcmp(buf,"Date",4,0)) {
  10878. srv_t = http_date(&buf[4]);
  10879. #endif /* CMDATE2TM */
  10880. } else if (!ckstrcmp(buf,"Connection:",11,0)) {
  10881. if ( ckindex("close",buf,11,0,0) != 0 )
  10882. closecon = 1;
  10883. } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
  10884. len = atoi(&buf[16]);
  10885. } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
  10886. if ( ckindex("chunked",buf,18,0,0) != 0 )
  10887. chunked = 1;
  10888. debug(F101,"http_get chunked","",chunked);
  10889. }
  10890. i = 0;
  10891. } else {
  10892. i++;
  10893. }
  10894. }
  10895. if (ch < 0 && first) {
  10896. first--;
  10897. http_close();
  10898. http_reopen();
  10899. goto getreq;
  10900. }
  10901. if (http_fnd == 0) {
  10902. rc = -1;
  10903. closecon = 1;
  10904. goto getexit;
  10905. }
  10906. /* Now we have the contents of the file */
  10907. if ( local && local[0] ) {
  10908. if (zopeno(ZOFILE,local,NULL,NULL))
  10909. zfile = 1;
  10910. else
  10911. rc = -1;
  10912. }
  10913. if ( chunked ) {
  10914. while ((len = http_get_chunk_len()) > 0) {
  10915. while (len && (ch = http_inc(0)) >= 0) {
  10916. len--;
  10917. if ( zfile )
  10918. zchout(ZOFILE,(CHAR)ch);
  10919. if ( stdio )
  10920. conoc((CHAR)ch);
  10921. }
  10922. if ((ch = http_inc(0)) != CR)
  10923. break;
  10924. if ((ch = http_inc(0)) != LF)
  10925. break;
  10926. }
  10927. } else {
  10928. while (len && (ch = http_inc(0)) >= 0) {
  10929. len--;
  10930. if ( zfile )
  10931. zchout(ZOFILE,(CHAR)ch);
  10932. if ( stdio )
  10933. conoc((CHAR)ch);
  10934. }
  10935. }
  10936. if ( zfile )
  10937. zclose(ZOFILE);
  10938. if ( chunked ) { /* Parse Trailing Headers */
  10939. nullline = 0;
  10940. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  10941. buf[i] = ch;
  10942. if ( buf[i] == 10 ) { /* found end of line */
  10943. if (i > 0 && buf[i-1] == 13)
  10944. i--;
  10945. if (i < 1)
  10946. nullline = 1;
  10947. buf[i] = '\0';
  10948. if (array && !nullline && hdcnt < HTTPHEADCNT)
  10949. makestr(&headers[hdcnt++],buf);
  10950. #ifdef CMDATE2TM
  10951. if (!ckstrcmp(buf,"Last-Modified",13,0)) {
  10952. mod_t = http_date(&buf[15]);
  10953. } else if (!ckstrcmp(buf,"Date",4,0)) {
  10954. srv_t = http_date(&buf[4]);
  10955. }
  10956. #endif /* CMDATE2TM */
  10957. else if (!ckstrcmp(buf,"Connection:",11,0)) {
  10958. if ( ckindex("close",buf,11,0,0) != 0 )
  10959. closecon = 1;
  10960. }
  10961. i = 0;
  10962. } else {
  10963. i++;
  10964. }
  10965. }
  10966. }
  10967. if ( zfile ) { /* Set timestamp */
  10968. #ifndef NOSETTIME
  10969. #ifdef OS2
  10970. u_t.actime = srv_t ? srv_t : local_t;
  10971. u_t.modtime = mod_t ? mod_t : local_t;
  10972. #else /* OS2 */
  10973. #ifdef SYSUTIMEH
  10974. u_t.actime = srv_t ? srv_t : local_t;
  10975. u_t.modtime = mod_t ? mod_t : local_t;
  10976. #else
  10977. #ifdef BSD44
  10978. u_t[0].tv_sec = srv_t ? srv_t : local_t;
  10979. u_t[1].tv_sec = mod_t ? mod_t : local_t;
  10980. #else
  10981. u_t.mtime = srv_t ? srv_t : local_t;
  10982. u_t.atime = mod_t ? mod_t : local_t;
  10983. #endif /* BSD44 */
  10984. #endif /* SYSUTIMEH */
  10985. #endif /* OS2 */
  10986. utime(local,&u_t);
  10987. #endif /* NOSETTIME */
  10988. }
  10989. getexit:
  10990. if (array)
  10991. http_mkarray(headers,hdcnt,array);
  10992. if ( closecon )
  10993. http_close();
  10994. free(request);
  10995. for (i = 0; i < hdcnt; i++) {
  10996. if (headers[i])
  10997. free(headers[i]);
  10998. }
  10999. return(rc);
  11000. }
  11001. int
  11002. #ifdef CK_ANSIC
  11003. http_head(char * agent, char ** hdrlist, char * user,
  11004. char * pwd, char array, char * local, char * remote,
  11005. int stdio)
  11006. #else
  11007. http_head(agent, hdrlist, user, pwd, array, local, remote, stdio)
  11008. char * agent; char ** hdrlist; char * user;
  11009. char * pwd; char array; char * local; char * remote;
  11010. int stdio;
  11011. #endif /* CK_ANSIC */
  11012. {
  11013. char * request = NULL;
  11014. int i, j, len = 0, hdcnt = 0, rc = 0;
  11015. int ch;
  11016. int http_fnd = 0;
  11017. char buf[HTTPBUFLEN], *p;
  11018. int nullline;
  11019. time_t mod_t;
  11020. time_t srv_t;
  11021. time_t local_t;
  11022. char passwd[64];
  11023. char b64in[128];
  11024. char b64out[256];
  11025. char * headers[HTTPHEADCNT];
  11026. int closecon = 0;
  11027. int first = 1;
  11028. if (httpfd == -1)
  11029. return(-1);
  11030. if (array) {
  11031. for (i = 0; i < HTTPHEADCNT; i++)
  11032. headers[i] = NULL;
  11033. }
  11034. len = 9; /* HEAD */
  11035. len += strlen(HTTP_VERSION);
  11036. len += strlen(remote);
  11037. len += 16;
  11038. if ( hdrlist ) {
  11039. for (i = 0; hdrlist[i]; i++)
  11040. len += strlen(hdrlist[i]) + 2;
  11041. }
  11042. len += strlen(http_host_port) + 8;
  11043. if (agent)
  11044. len += 13 + strlen(agent);
  11045. if (user) {
  11046. if (!pwd) {
  11047. readpass("Password: ",passwd,64);
  11048. pwd = passwd;
  11049. }
  11050. ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
  11051. j = b8tob64(b64in,strlen(b64in),b64out,256);
  11052. memset(pwd,0,strlen(pwd)); /* NOT PORTABLE */
  11053. if (j < 0)
  11054. return(-1);
  11055. b64out[j] = '\0';
  11056. len += j + 24;
  11057. }
  11058. #ifdef HTTP_CLOSE
  11059. len += 19; /* Connection: close */
  11060. #endif
  11061. len += 3; /* blank line + null */
  11062. request = (char *)malloc(len);
  11063. if (!request)
  11064. return(-1);
  11065. sprintf(request,"HEAD %s %s\r\n",remote,HTTP_VERSION);
  11066. ckstrncat(request,"Host: ", len);
  11067. ckstrncat(request,http_host_port, len);
  11068. ckstrncat(request,"\r\n",len);
  11069. if (agent) {
  11070. ckstrncat(request,"User-agent: ",len);
  11071. ckstrncat(request,agent,len);
  11072. ckstrncat(request,"\r\n",len);
  11073. }
  11074. if (user) {
  11075. ckstrncat(request,"Authorization: Basic ",len);
  11076. ckstrncat(request,b64out,len);
  11077. ckstrncat(request,"\r\n",len);
  11078. }
  11079. if ( hdrlist ) {
  11080. for (i = 0; hdrlist[i]; i++) {
  11081. ckstrncat(request,hdrlist[i],len);
  11082. ckstrncat(request,"\r\n",len);
  11083. }
  11084. }
  11085. #ifdef HTTP_CLOSE
  11086. ckstrncat(request,"Connection: close\r\n",len);
  11087. #endif
  11088. ckstrncat(request,"\r\n",len);
  11089. if ( local && local[0] ) {
  11090. if (!zopeno(ZOFILE,local,NULL,NULL)) {
  11091. free(request);
  11092. return(-1);
  11093. }
  11094. }
  11095. headreq:
  11096. if (http_tol((CHAR *)request,strlen(request)) < 0)
  11097. {
  11098. http_close();
  11099. if ( first ) {
  11100. first--;
  11101. http_reopen();
  11102. goto headreq;
  11103. }
  11104. rc = -1;
  11105. goto headexit;
  11106. }
  11107. /* Process the headers */
  11108. local_t = time(NULL);
  11109. nullline = 0;
  11110. i = 0;
  11111. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  11112. buf[i] = ch;
  11113. if (buf[i] == 10) { /* found end of line */
  11114. if (i > 0 && buf[i-1] == 13)
  11115. i--;
  11116. if (i < 1)
  11117. nullline = 1;
  11118. buf[i] = '\0';
  11119. if (array && !nullline && hdcnt < HTTPHEADCNT)
  11120. makestr(&headers[hdcnt++],buf);
  11121. if (!ckstrcmp(buf,"HTTP",4,0)) {
  11122. http_fnd = 1;
  11123. j = ckindex(" ",buf,0,0,0);
  11124. p = &buf[j];
  11125. while (isspace(*p))
  11126. p++;
  11127. switch (p[0]) {
  11128. case '1': /* Informational message */
  11129. break;
  11130. case '2': /* Success */
  11131. break;
  11132. case '3': /* Redirection */
  11133. case '4': /* Client failure */
  11134. case '5': /* Server failure */
  11135. default: /* Unknown */
  11136. if (!quiet)
  11137. printf("Failure: Server reports %s\n",p);
  11138. rc = -1;
  11139. }
  11140. http_set_code_reply(p);
  11141. } else {
  11142. if (!ckstrcmp(buf,"Connection:",11,0)) {
  11143. if ( ckindex("close",buf,11,0,0) != 0 )
  11144. closecon = 1;
  11145. }
  11146. if ( local && local[0] ) {
  11147. zsout(ZOFILE,buf);
  11148. zsout(ZOFILE,"\r\n");
  11149. }
  11150. if (stdio)
  11151. printf("%s\r\n",buf);
  11152. }
  11153. i = 0;
  11154. } else {
  11155. i++;
  11156. }
  11157. }
  11158. if (ch < 0 && first) {
  11159. first--;
  11160. http_close();
  11161. http_reopen();
  11162. goto headreq;
  11163. }
  11164. if ( http_fnd == 0 )
  11165. rc = -1;
  11166. if (array)
  11167. http_mkarray(headers,hdcnt,array);
  11168. headexit:
  11169. if ( local && local[0] )
  11170. zclose(ZOFILE);
  11171. if (closecon)
  11172. http_close();
  11173. free(request);
  11174. for (i = 0; i < hdcnt; i++) {
  11175. if (headers[i])
  11176. free(headers[i]);
  11177. }
  11178. return(rc);
  11179. }
  11180. int
  11181. #ifdef CK_ANSIC
  11182. http_index(char * agent, char ** hdrlist, char * user, char * pwd,
  11183. char array, char * local, char * remote, int stdio)
  11184. #else
  11185. http_index(agent, hdrlist, user, pwd, array, local, remote, stdio)
  11186. char * agent; char ** hdrlist; char * user; char * pwd;
  11187. char array; char * local; char * remote; int stdio;
  11188. #endif /* CK_ANSIC */
  11189. {
  11190. char * request = NULL;
  11191. int i, j, len = 0, hdcnt = 0, rc = 0;
  11192. int ch;
  11193. int http_fnd = 0;
  11194. char buf[HTTPBUFLEN], *p;
  11195. int nullline;
  11196. time_t mod_t;
  11197. time_t srv_t;
  11198. time_t local_t;
  11199. char passwd[64];
  11200. char b64in[128];
  11201. char b64out[256];
  11202. char * headers[HTTPHEADCNT];
  11203. int closecon = 0;
  11204. int chunked = 0;
  11205. int zfile = 0;
  11206. int first = 1;
  11207. if (httpfd == -1)
  11208. return(-1);
  11209. if (array) {
  11210. for (i = 0; i < HTTPHEADCNT; i++)
  11211. headers[i] = NULL;
  11212. }
  11213. len = 10; /* INDEX */
  11214. len += strlen(HTTP_VERSION);
  11215. len += strlen(remote);
  11216. len += 16;
  11217. if ( hdrlist ) {
  11218. for (i = 0; hdrlist[i]; i++)
  11219. len += strlen(hdrlist[i]) + 2;
  11220. }
  11221. len += strlen(http_host_port) + 8;
  11222. if (agent)
  11223. len += 13 + strlen(agent);
  11224. if (user) {
  11225. if (!pwd) {
  11226. readpass("Password: ",passwd,64);
  11227. pwd = passwd;
  11228. }
  11229. ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
  11230. j = b8tob64(b64in,strlen(b64in),b64out,256);
  11231. memset(pwd,0,strlen(pwd));
  11232. if (j < 0)
  11233. return(-1);
  11234. b64out[j] = '\0';
  11235. len += j + 24;
  11236. }
  11237. #ifdef HTTP_CLOSE
  11238. len += 19; /* Connection: close */
  11239. #endif
  11240. len += 3; /* blank line + null */
  11241. request = malloc(len);
  11242. if (!request)
  11243. return(-1);
  11244. sprintf(request,"INDEX %s\r\n",HTTP_VERSION);
  11245. ckstrncat(request,"Host: ", len);
  11246. ckstrncat(request,http_host_port, len);
  11247. ckstrncat(request,"\r\n",len);
  11248. if (agent) {
  11249. ckstrncat(request,"User-agent: ",len);
  11250. ckstrncat(request,agent,len);
  11251. ckstrncat(request,"\r\n",len);
  11252. }
  11253. if (user) {
  11254. ckstrncat(request,"Authorization: Basic ",len);
  11255. ckstrncat(request,b64out,len);
  11256. ckstrncat(request,"\r\n",len);
  11257. }
  11258. if ( hdrlist ) {
  11259. for (i = 0; hdrlist[i]; i++) {
  11260. ckstrncat(request,hdrlist[i],len);
  11261. ckstrncat(request,"\r\n",len);
  11262. }
  11263. }
  11264. #ifdef HTTP_CLOSE
  11265. ckstrncat(request,"Connection: close\r\n",len);
  11266. #endif
  11267. ckstrncat(request,"\r\n",len);
  11268. indexreq:
  11269. if (http_tol((CHAR *)request,strlen(request)) < 0)
  11270. {
  11271. http_close();
  11272. if ( first ) {
  11273. first--;
  11274. http_reopen();
  11275. goto indexreq;
  11276. }
  11277. rc = -1;
  11278. goto indexexit;
  11279. }
  11280. /* Process the headers */
  11281. local_t = time(NULL);
  11282. nullline = 0;
  11283. i = 0;
  11284. len = -1;
  11285. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  11286. buf[i] = ch;
  11287. if (buf[i] == 10) { /* found end of line */
  11288. if (i > 0 && buf[i-1] == 13)
  11289. i--;
  11290. if (i < 1)
  11291. nullline = 1;
  11292. buf[i] = '\0';
  11293. if (array && !nullline && hdcnt < HTTPHEADCNT)
  11294. makestr(&headers[hdcnt++],buf);
  11295. if (!ckstrcmp(buf,"HTTP",4,0)) {
  11296. http_fnd = 1;
  11297. j = ckindex(" ",buf,0,0,0);
  11298. p = &buf[j];
  11299. while (isspace(*p))
  11300. p++;
  11301. switch ( p[0] ) {
  11302. case '1': /* Informational message */
  11303. break;
  11304. case '2': /* Success */
  11305. break;
  11306. case '3': /* Redirection */
  11307. case '4': /* Client failure */
  11308. case '5': /* Server failure */
  11309. default: /* Unknown */
  11310. if (!quiet)
  11311. printf("Failure: Server reports %s\n",p);
  11312. rc = -1;
  11313. }
  11314. http_set_code_reply(p);
  11315. } else if ( !nullline ) {
  11316. if (!ckstrcmp(buf,"Connection:",11,0)) {
  11317. if ( ckindex("close",buf,11,0,0) != 0 )
  11318. closecon = 1;
  11319. } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
  11320. len = atoi(&buf[16]);
  11321. } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
  11322. if ( ckindex("chunked",buf,18,0,0) != 0 )
  11323. chunked = 1;
  11324. debug(F101,"http_index chunked","",chunked);
  11325. }
  11326. printf("%s\n",buf);
  11327. }
  11328. i = 0;
  11329. } else {
  11330. i++;
  11331. }
  11332. }
  11333. if (ch < 0 && first) {
  11334. first--;
  11335. http_close();
  11336. http_reopen();
  11337. goto indexreq;
  11338. }
  11339. if ( http_fnd == 0 ) {
  11340. rc = -1;
  11341. closecon = 1;
  11342. goto indexexit;
  11343. }
  11344. /* Now we have the contents of the file */
  11345. if ( local && local[0] ) {
  11346. if (zopeno(ZOFILE,local,NULL,NULL))
  11347. zfile = 1;
  11348. else
  11349. rc = -1;
  11350. }
  11351. if ( chunked ) {
  11352. while ((len = http_get_chunk_len()) > 0) {
  11353. while (len && (ch = http_inc(0)) >= 0) {
  11354. len--;
  11355. if ( zfile )
  11356. zchout(ZOFILE,(CHAR)ch);
  11357. if ( stdio )
  11358. conoc((CHAR)ch);
  11359. }
  11360. if ((ch = http_inc(0)) != CR)
  11361. break;
  11362. if ((ch = http_inc(0)) != LF)
  11363. break;
  11364. }
  11365. } else {
  11366. while (len && (ch = http_inc(0)) >= 0) {
  11367. len--;
  11368. if ( zfile )
  11369. zchout(ZOFILE,(CHAR)ch);
  11370. if ( stdio )
  11371. conoc((CHAR)ch);
  11372. }
  11373. }
  11374. if ( zfile )
  11375. zclose(ZOFILE);
  11376. if ( chunked ) { /* Parse Trailing Headers */
  11377. nullline = 0;
  11378. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  11379. buf[i] = ch;
  11380. if ( buf[i] == 10 ) { /* found end of line */
  11381. if (i > 0 && buf[i-1] == 13)
  11382. i--;
  11383. if (i < 1)
  11384. nullline = 1;
  11385. buf[i] = '\0';
  11386. if (array && !nullline && hdcnt < HTTPHEADCNT)
  11387. makestr(&headers[hdcnt++],buf);
  11388. if (!ckstrcmp(buf,"Connection:",11,0)) {
  11389. if ( ckindex("close",buf,11,0,0) != 0 )
  11390. closecon = 1;
  11391. }
  11392. i = 0;
  11393. } else {
  11394. i++;
  11395. }
  11396. }
  11397. }
  11398. rc = 0;
  11399. indexexit:
  11400. if (array)
  11401. http_mkarray(headers,hdcnt,array);
  11402. if (closecon)
  11403. http_close();
  11404. free(request);
  11405. for (i = 0; i < hdcnt; i++) {
  11406. if (headers[i])
  11407. free(headers[i]);
  11408. }
  11409. return(rc);
  11410. }
  11411. int
  11412. #ifdef CK_ANSIC
  11413. http_put(char * agent, char ** hdrlist, char * mime, char * user,
  11414. char * pwd, char array, char * local, char * remote,
  11415. char * dest, int stdio)
  11416. #else
  11417. http_put(agent, hdrlist, mime, user, pwd, array, local, remote, dest, stdio)
  11418. char * agent; char ** hdrlist; char * mime; char * user;
  11419. char * pwd; char array; char * local; char * remote; char * dest;
  11420. int stdio;
  11421. #endif /* CK_ANSIC */
  11422. {
  11423. char * request=NULL;
  11424. int i, j, len = 0, hdcnt = 0, rc = 0;
  11425. int ch;
  11426. int http_fnd = 0;
  11427. char buf[HTTPBUFLEN], *p;
  11428. int nullline;
  11429. time_t mod_t;
  11430. time_t srv_t;
  11431. time_t local_t;
  11432. char passwd[64];
  11433. char b64in[128];
  11434. char b64out[256];
  11435. int filelen;
  11436. char * headers[HTTPHEADCNT];
  11437. int closecon = 0;
  11438. int chunked = 0;
  11439. int first = 1;
  11440. int zfile = 0;
  11441. if (httpfd == -1)
  11442. return(-1);
  11443. if (!mime) mime = "";
  11444. if (!remote) remote = "";
  11445. if (!local) local = "";
  11446. if (!*local) return(-1);
  11447. if (array) {
  11448. for (i = 0; i < HTTPHEADCNT; i++)
  11449. headers[i] = NULL;
  11450. }
  11451. filelen = zchki(local);
  11452. if (filelen < 0)
  11453. return(-1);
  11454. /* Compute length of request header */
  11455. len = 8; /* PUT */
  11456. len += strlen(HTTP_VERSION);
  11457. len += strlen(remote);
  11458. len += 16;
  11459. if ( hdrlist ) {
  11460. for (i = 0; hdrlist[i]; i++)
  11461. len += strlen(hdrlist[i]) + 2;
  11462. }
  11463. len += strlen(http_host_port) + 8;
  11464. if (agent)
  11465. len += 13 + strlen(agent);
  11466. if (user) {
  11467. if (!pwd) {
  11468. readpass("Password: ",passwd,64);
  11469. pwd = passwd;
  11470. }
  11471. ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
  11472. j = b8tob64(b64in,strlen(b64in),b64out,256);
  11473. memset(pwd,0,strlen(pwd));
  11474. if (j < 0)
  11475. return(-1);
  11476. b64out[j] = '\0';
  11477. len += j + 24;
  11478. }
  11479. len += 16 + strlen(mime); /* Content-type: */
  11480. len += 32; /* Content-length: */
  11481. len += 32; /* Date: */
  11482. #ifdef HTTP_CLOSE
  11483. len += 19; /* Connection: close */
  11484. #endif
  11485. len += 3; /* blank line + null */
  11486. request = malloc(len);
  11487. if (!request)
  11488. return(-1);
  11489. sprintf(request,"PUT %s %s\r\n",remote,HTTP_VERSION);
  11490. ckstrncat(request,"Date: ",len);
  11491. #ifdef CMDATE2TM
  11492. ckstrncat(request,http_now(),len);
  11493. #else
  11494. ckstrncat(request,...,len);
  11495. #endif /* CMDATE2TM */
  11496. ckstrncat(request,"\r\n",len);
  11497. ckstrncat(request,"Host: ", len);
  11498. ckstrncat(request,http_host_port, len);
  11499. ckstrncat(request,"\r\n",len);
  11500. if (agent) {
  11501. ckstrncat(request,"User-agent: ",len);
  11502. ckstrncat(request,agent,len);
  11503. ckstrncat(request,"\r\n",len);
  11504. }
  11505. if (user) {
  11506. ckstrncat(request,"Authorization: Basic ",len);
  11507. ckstrncat(request,b64out,len);
  11508. ckstrncat(request,"\r\n",len);
  11509. }
  11510. if ( hdrlist ) {
  11511. for (i = 0; hdrlist[i]; i++) {
  11512. ckstrncat(request,hdrlist[i],len);
  11513. ckstrncat(request,"\r\n",len);
  11514. }
  11515. }
  11516. ckstrncat(request,"Content-type: ",len);
  11517. ckstrncat(request,mime,len);
  11518. ckstrncat(request,"\r\n",len);
  11519. sprintf(buf,"Content-length: %d\r\n",filelen); /* safe */
  11520. ckstrncat(request,buf,len);
  11521. #ifdef HTTP_CLOSE
  11522. ckstrncat(request,"Connection: close\r\n",len);
  11523. #endif
  11524. ckstrncat(request,"\r\n",len);
  11525. /* Now we have the contents of the file */
  11526. if (zopeni(ZIFILE,local)) {
  11527. putreq: /* Send request */
  11528. if (http_tol((CHAR *)request,strlen(request)) <= 0) {
  11529. http_close();
  11530. if ( first ) {
  11531. first--;
  11532. http_reopen();
  11533. goto putreq;
  11534. }
  11535. zclose(ZIFILE);
  11536. rc = -1;
  11537. goto putexit;
  11538. }
  11539. /* Request headers have been sent */
  11540. i = 0;
  11541. while (zchin(ZIFILE,&ch) == 0) {
  11542. buf[i++] = ch;
  11543. if (i == HTTPBUFLEN) {
  11544. if (http_tol((CHAR *)buf,HTTPBUFLEN) <= 0) {
  11545. http_close();
  11546. if ( first ) {
  11547. first--;
  11548. http_reopen();
  11549. goto putreq;
  11550. }
  11551. }
  11552. i = 0;
  11553. }
  11554. }
  11555. if (i > 0) {
  11556. if (http_tol((CHAR *)buf,i) < 0) {
  11557. http_close();
  11558. if ( first ) {
  11559. first--;
  11560. http_reopen();
  11561. goto putreq;
  11562. }
  11563. }
  11564. }
  11565. zclose(ZIFILE);
  11566. /* Process the response headers */
  11567. local_t = time(NULL);
  11568. nullline = 0;
  11569. i = 0;
  11570. len = -1;
  11571. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  11572. buf[i] = ch;
  11573. if (buf[i] == 10) { /* found end of line */
  11574. if (i > 0 && buf[i-1] == 13)
  11575. i--;
  11576. if (i < 1)
  11577. nullline = 1;
  11578. buf[i] = '\0';
  11579. if (array && !nullline && hdcnt < HTTPHEADCNT)
  11580. makestr(&headers[hdcnt++],buf);
  11581. if (!ckstrcmp(buf,"HTTP",4,0)) {
  11582. http_fnd = 1;
  11583. j = ckindex(" ",buf,0,0,0);
  11584. p = &buf[j];
  11585. while (isspace(*p))
  11586. p++;
  11587. switch (p[0]) {
  11588. case '1': /* Informational message */
  11589. break;
  11590. case '2': /* Success */
  11591. break;
  11592. case '3': /* Redirection */
  11593. case '4': /* Client failure */
  11594. case '5': /* Server failure */
  11595. default: /* Unknown */
  11596. if (!quiet)
  11597. printf("Failure: Server reports %s\n",p);
  11598. rc = -1;
  11599. }
  11600. http_set_code_reply(p);
  11601. } else {
  11602. if (!ckstrcmp(buf,"Connection:",11,0)) {
  11603. if ( ckindex("close",buf,11,0,0) != 0 )
  11604. closecon = 1;
  11605. } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
  11606. len = atoi(&buf[16]);
  11607. } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
  11608. if ( ckindex("chunked",buf,18,0,0) != 0 )
  11609. chunked = 1;
  11610. debug(F101,"http_put chunked","",chunked);
  11611. }
  11612. if ( stdio )
  11613. printf("%s\n",buf);
  11614. }
  11615. i = 0;
  11616. } else {
  11617. i++;
  11618. }
  11619. }
  11620. if (ch < 0 && first) {
  11621. first--;
  11622. http_close();
  11623. http_reopen();
  11624. goto putreq;
  11625. }
  11626. if ( http_fnd == 0 ) {
  11627. closecon = 1;
  11628. rc = -1;
  11629. goto putexit;
  11630. }
  11631. /* Any response data? */
  11632. if ( dest && dest[0] ) {
  11633. if (zopeno(ZOFILE,dest,NULL,NULL))
  11634. zfile = 1;
  11635. else
  11636. rc = -1;
  11637. }
  11638. if ( chunked ) {
  11639. while ((len = http_get_chunk_len()) > 0) {
  11640. while (len && (ch = http_inc(0)) >= 0) {
  11641. len--;
  11642. if ( zfile )
  11643. zchout(ZOFILE,(CHAR)ch);
  11644. if ( stdio )
  11645. conoc((CHAR)ch);
  11646. }
  11647. if ((ch = http_inc(0)) != CR)
  11648. break;
  11649. if ((ch = http_inc(0)) != LF)
  11650. break;
  11651. }
  11652. } else {
  11653. while (len && (ch = http_inc(0)) >= 0) {
  11654. len--;
  11655. if ( zfile )
  11656. zchout(ZOFILE,(CHAR)ch);
  11657. if ( stdio )
  11658. conoc((CHAR)ch);
  11659. }
  11660. }
  11661. if ( zfile )
  11662. zclose(ZOFILE);
  11663. if ( chunked ) { /* Parse Trailing Headers */
  11664. nullline = 0;
  11665. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  11666. buf[i] = ch;
  11667. if ( buf[i] == 10 ) { /* found end of line */
  11668. if (i > 0 && buf[i-1] == 13)
  11669. i--;
  11670. if (i < 1)
  11671. nullline = 1;
  11672. buf[i] = '\0';
  11673. if (array && !nullline && hdcnt < HTTPHEADCNT)
  11674. makestr(&headers[hdcnt++],buf);
  11675. if (!ckstrcmp(buf,"Connection:",11,0)) {
  11676. if ( ckindex("close",buf,11,0,0) != 0 )
  11677. closecon = 1;
  11678. }
  11679. i = 0;
  11680. } else {
  11681. i++;
  11682. }
  11683. }
  11684. }
  11685. } else {
  11686. rc = -1;
  11687. }
  11688. putexit:
  11689. if ( array )
  11690. http_mkarray(headers,hdcnt,array);
  11691. if (closecon)
  11692. http_close();
  11693. free(request);
  11694. for (i = 0; i < hdcnt; i++) {
  11695. if (headers[i])
  11696. free(headers[i]);
  11697. }
  11698. return(rc);
  11699. }
  11700. int
  11701. #ifdef CK_ANSIC
  11702. http_delete(char * agent, char ** hdrlist, char * user,
  11703. char * pwd, char array, char * remote)
  11704. #else
  11705. http_delete(agent, hdrlist, user, pwd, array, remote)
  11706. char * agent; char ** hdrlist; char * user;
  11707. char * pwd; char array; char * remote;
  11708. #endif /* CK_ANSIC */
  11709. {
  11710. char * request=NULL;
  11711. int i, j, len = 0, hdcnt = 0, rc = 0;
  11712. int ch;
  11713. int http_fnd = 0;
  11714. char buf[HTTPBUFLEN], *p;
  11715. int nullline;
  11716. time_t mod_t;
  11717. time_t srv_t;
  11718. time_t local_t;
  11719. char passwd[64];
  11720. char b64in[128];
  11721. char b64out[256];
  11722. char * headers[HTTPHEADCNT];
  11723. int closecon = 0;
  11724. int chunked = 0;
  11725. int first = 1;
  11726. if (httpfd == -1)
  11727. return(-1);
  11728. if (array) {
  11729. for (i = 0; i < HTTPHEADCNT; i++)
  11730. headers[i] = NULL;
  11731. }
  11732. /* Compute length of request header */
  11733. len = 11; /* DELETE */
  11734. len += strlen(HTTP_VERSION);
  11735. len += strlen(remote);
  11736. len += 16;
  11737. if ( hdrlist ) {
  11738. for (i = 0; hdrlist[i]; i++)
  11739. len += strlen(hdrlist[i]) + 2;
  11740. }
  11741. len += strlen(http_host_port) + 8;
  11742. if (agent)
  11743. len += 13 + strlen(agent);
  11744. if (user) {
  11745. if (!pwd) {
  11746. readpass("Password: ",passwd,64);
  11747. pwd = passwd;
  11748. }
  11749. ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
  11750. j = b8tob64(b64in,strlen(b64in),b64out,256);
  11751. memset(pwd,0,strlen(pwd));
  11752. if (j < 0)
  11753. return(-1);
  11754. b64out[j] = '\0';
  11755. len += j + 24;
  11756. }
  11757. len += 32; /* Date: */
  11758. #ifdef HTTP_CLOSE
  11759. len += 19; /* Connection: close */
  11760. #endif
  11761. len += 3; /* blank line + null */
  11762. request = malloc(len);
  11763. if (!request)
  11764. return(-1);
  11765. sprintf(request,"DELETE %s %s\r\n",remote,HTTP_VERSION);
  11766. ckstrncat(request,"Date: ",len);
  11767. #ifdef CMDATE2TM
  11768. ckstrncat(request,http_now(),len);
  11769. #else
  11770. ckstrncat(request,...,len);
  11771. #endif /* CMDATE2TM */
  11772. ckstrncat(request,"\r\n",len);
  11773. ckstrncat(request,"Host: ", len);
  11774. ckstrncat(request,http_host_port, len);
  11775. ckstrncat(request,"\r\n",len);
  11776. if (agent) {
  11777. ckstrncat(request,"User-agent: ",len);
  11778. ckstrncat(request,agent,len);
  11779. ckstrncat(request,"\r\n",len);
  11780. }
  11781. if (user) {
  11782. ckstrncat(request,"Authorization: Basic ",len);
  11783. ckstrncat(request,b64out,len);
  11784. ckstrncat(request,"\r\n",len);
  11785. }
  11786. if ( hdrlist ) {
  11787. for (i = 0; hdrlist[i]; i++) {
  11788. ckstrncat(request,hdrlist[i],len);
  11789. ckstrncat(request,"\r\n",len);
  11790. }
  11791. }
  11792. #ifdef HTTP_CLOSE
  11793. ckstrncat(request,"Connection: close\r\n",len);
  11794. #endif
  11795. ckstrncat(request,"\r\n",len);
  11796. delreq:
  11797. if (http_tol((CHAR *)request,strlen(request)) < 0)
  11798. {
  11799. http_close();
  11800. if ( first ) {
  11801. first--;
  11802. http_reopen();
  11803. goto delreq;
  11804. }
  11805. rc = -1;
  11806. goto delexit;
  11807. }
  11808. /* Process the response headers */
  11809. local_t = time(NULL);
  11810. nullline = 0;
  11811. i = 0;
  11812. len = -1;
  11813. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  11814. buf[i] = ch;
  11815. if (buf[i] == 10) { /* found end of line */
  11816. if (i > 0 && buf[i-1] == 13)
  11817. i--;
  11818. if (i < 1)
  11819. nullline = 1;
  11820. buf[i] = '\0';
  11821. if (array && !nullline && hdcnt < HTTPHEADCNT)
  11822. makestr(&headers[hdcnt++],buf);
  11823. if (!ckstrcmp(buf,"HTTP",4,0)) {
  11824. http_fnd = 1;
  11825. j = ckindex(" ",buf,0,0,0);
  11826. p = &buf[j];
  11827. while (isspace(*p))
  11828. p++;
  11829. switch (p[0]) {
  11830. case '1': /* Informational message */
  11831. break;
  11832. case '2': /* Success */
  11833. break;
  11834. case '3': /* Redirection */
  11835. case '4': /* Client failure */
  11836. case '5': /* Server failure */
  11837. default: /* Unknown */
  11838. if (!quiet)
  11839. printf("Failure: Server reports %s\n",p);
  11840. rc = -1;
  11841. }
  11842. http_set_code_reply(p);
  11843. } else {
  11844. if (!ckstrcmp(buf,"Connection:",11,0)) {
  11845. if ( ckindex("close",buf,11,0,0) != 0 )
  11846. closecon = 1;
  11847. } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
  11848. len = atoi(&buf[16]);
  11849. } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
  11850. if ( ckindex("chunked",buf,18,0,0) != 0 )
  11851. chunked = 1;
  11852. debug(F101,"http_delete chunked","",chunked);
  11853. }
  11854. printf("%s\n",buf);
  11855. }
  11856. i = 0;
  11857. } else {
  11858. i++;
  11859. }
  11860. }
  11861. if (ch < 0 && first) {
  11862. first--;
  11863. http_close();
  11864. http_reopen();
  11865. goto delreq;
  11866. }
  11867. if ( http_fnd == 0 ) {
  11868. rc = -1;
  11869. closecon = 1;
  11870. goto delexit;
  11871. }
  11872. /* Any response data? */
  11873. if ( chunked ) {
  11874. while ((len = http_get_chunk_len()) > 0) {
  11875. while (len && (ch = http_inc(0)) >= 0) {
  11876. len--;
  11877. conoc((CHAR)ch);
  11878. }
  11879. if ((ch = http_inc(0)) != CR)
  11880. break;
  11881. if ((ch = http_inc(0)) != LF)
  11882. break;
  11883. }
  11884. } else {
  11885. while (len && (ch = http_inc(0)) >= 0) {
  11886. len--;
  11887. conoc((CHAR)ch);
  11888. }
  11889. }
  11890. if ( chunked ) { /* Parse Trailing Headers */
  11891. nullline = 0;
  11892. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  11893. buf[i] = ch;
  11894. if ( buf[i] == 10 ) { /* found end of line */
  11895. if (i > 0 && buf[i-1] == 13)
  11896. i--;
  11897. if (i < 1)
  11898. nullline = 1;
  11899. buf[i] = '\0';
  11900. if (array && !nullline && hdcnt < HTTPHEADCNT)
  11901. makestr(&headers[hdcnt++],buf);
  11902. if (!ckstrcmp(buf,"Connection:",11,0)) {
  11903. if ( ckindex("close",buf,11,0,0) != 0 )
  11904. closecon = 1;
  11905. }
  11906. i = 0;
  11907. } else {
  11908. i++;
  11909. }
  11910. }
  11911. }
  11912. delexit:
  11913. if (array)
  11914. http_mkarray(headers,hdcnt,array);
  11915. if (closecon)
  11916. http_close();
  11917. free(request);
  11918. for (i = 0; i < hdcnt; i++) {
  11919. if (headers[i])
  11920. free(headers[i]);
  11921. }
  11922. return(rc);
  11923. }
  11924. int
  11925. #ifdef CK_ANSIC
  11926. http_post(char * agent, char ** hdrlist, char * mime, char * user,
  11927. char * pwd, char array, char * local, char * remote,
  11928. char * dest, int stdio)
  11929. #else
  11930. http_post(agent, hdrlist, mime, user, pwd, array, local, remote, dest,
  11931. stdio)
  11932. char * agent; char ** hdrlist; char * mime; char * user;
  11933. char * pwd; char array; char * local; char * remote; char * dest;
  11934. int stdio;
  11935. #endif /* CK_ANSIC */
  11936. {
  11937. char * request=NULL;
  11938. int i, j, len = 0, hdcnt = 0, rc = 0;
  11939. int ch;
  11940. int http_fnd = 0;
  11941. char buf[HTTPBUFLEN], *p;
  11942. int nullline;
  11943. time_t mod_t;
  11944. time_t srv_t;
  11945. time_t local_t;
  11946. char passwd[64];
  11947. char b64in[128];
  11948. char b64out[256];
  11949. int filelen;
  11950. char * headers[HTTPHEADCNT];
  11951. int closecon = 0;
  11952. int chunked = 0;
  11953. int zfile = 0;
  11954. int first = 1;
  11955. if (httpfd == -1)
  11956. return(-1);
  11957. if (array) {
  11958. for (i = 0; i < HTTPHEADCNT; i++)
  11959. headers[i] = NULL;
  11960. }
  11961. filelen = zchki(local);
  11962. if (filelen < 0)
  11963. return(-1);
  11964. /* Compute length of request header */
  11965. len = 9; /* POST */
  11966. len += strlen(HTTP_VERSION);
  11967. len += strlen(remote);
  11968. len += 16;
  11969. if ( hdrlist ) {
  11970. for (i = 0; hdrlist[i]; i++)
  11971. len += strlen(hdrlist[i]) + 2;
  11972. }
  11973. len += strlen(http_host_port) + 8;
  11974. if (agent)
  11975. len += 13 + strlen(agent);
  11976. if (user) {
  11977. if (!pwd) {
  11978. readpass("Password: ",passwd,64);
  11979. pwd = passwd;
  11980. }
  11981. ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
  11982. j = b8tob64(b64in,strlen(b64in),b64out,256);
  11983. memset(pwd,0,strlen(pwd));
  11984. if (j < 0)
  11985. return(-1);
  11986. b64out[j] = '\0';
  11987. len += j + 24;
  11988. }
  11989. len += 16 + strlen(mime); /* Content-type: */
  11990. len += 32; /* Content-length: */
  11991. len += 32; /* Date: */
  11992. #ifdef HTTP_CLOSE
  11993. len += 19; /* Connection: close */
  11994. #endif
  11995. len += 3; /* blank line + null */
  11996. request = malloc(len);
  11997. if (!request)
  11998. return(-1);
  11999. sprintf(request,"POST %s %s\r\n",remote,HTTP_VERSION);
  12000. ckstrncat(request,"Date: ",len);
  12001. ckstrncat(request,http_now(),len);
  12002. ckstrncat(request,"\r\n",len);
  12003. ckstrncat(request,"Host: ", len);
  12004. ckstrncat(request,http_host_port, len);
  12005. ckstrncat(request,"\r\n",len);
  12006. if (agent) {
  12007. ckstrncat(request,"User-agent: ",len);
  12008. ckstrncat(request,agent,len);
  12009. ckstrncat(request,"\r\n",len);
  12010. }
  12011. if (user) {
  12012. ckstrncat(request,"Authorization: Basic ",len);
  12013. ckstrncat(request,b64out,len);
  12014. ckstrncat(request,"\r\n",len);
  12015. }
  12016. if ( hdrlist ) {
  12017. for (i = 0; hdrlist[i]; i++) {
  12018. ckstrncat(request,hdrlist[i],len);
  12019. ckstrncat(request,"\r\n",len);
  12020. }
  12021. }
  12022. ckstrncat(request,"Content-type: ",len);
  12023. ckstrncat(request,mime,len);
  12024. ckstrncat(request,"\r\n",len);
  12025. #ifdef HTTP_CLOSE
  12026. ckstrncat(request,"Connection: close\r\n",len);
  12027. #endif
  12028. sprintf(buf,"Content-length: %d\r\n",filelen); /* safe */
  12029. ckstrncat(request,buf,len);
  12030. ckstrncat(request,"\r\n",len);
  12031. #ifdef COMMENT
  12032. /* This is apparently a mistake - the previous ckstrncat() already */
  12033. /* appended a blank line to the request. There should only be one. */
  12034. /* Servers are not required by RFC 2616 to ignore extraneous empty */
  12035. /* lines. -fdc, 28 Aug 2005. */
  12036. ckstrncat(request,"\r\n",len);
  12037. #endif /* COMMENT */
  12038. /* Now we have the contents of the file */
  12039. postopen:
  12040. if (zopeni(ZIFILE,local)) {
  12041. postreq:
  12042. if (http_tol((CHAR *)request,strlen(request)) < 0)
  12043. {
  12044. http_close();
  12045. if ( first ) {
  12046. first--;
  12047. http_reopen();
  12048. goto postreq;
  12049. }
  12050. rc = -1;
  12051. zclose(ZIFILE);
  12052. goto postexit;
  12053. }
  12054. i = 0;
  12055. while (zchin(ZIFILE,&ch) == 0) {
  12056. buf[i++] = ch;
  12057. if (i == HTTPBUFLEN) {
  12058. http_tol((CHAR *)buf,HTTPBUFLEN);
  12059. i = 0;
  12060. }
  12061. }
  12062. if (i > 0)
  12063. http_tol((CHAR *)buf,HTTPBUFLEN);
  12064. zclose(ZIFILE);
  12065. /* Process the response headers */
  12066. local_t = time(NULL);
  12067. nullline = 0;
  12068. i = 0;
  12069. len = -1;
  12070. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  12071. buf[i] = ch;
  12072. if (buf[i] == 10) { /* found end of line */
  12073. if (i > 0 && buf[i-1] == 13)
  12074. i--;
  12075. if (i < 1)
  12076. nullline = 1;
  12077. buf[i] = '\0';
  12078. if (array && !nullline && hdcnt < HTTPHEADCNT)
  12079. makestr(&headers[hdcnt++],buf);
  12080. if (!ckstrcmp(buf,"HTTP",4,0)) {
  12081. http_fnd = 1;
  12082. j = ckindex(" ",buf,0,0,0);
  12083. p = &buf[j];
  12084. while (isspace(*p))
  12085. p++;
  12086. switch (p[0]) {
  12087. case '1': /* Informational message */
  12088. break;
  12089. case '2': /* Success */
  12090. break;
  12091. case '3': /* Redirection */
  12092. case '4': /* Client failure */
  12093. case '5': /* Server failure */
  12094. default: /* Unknown */
  12095. if (!quiet)
  12096. printf("Failure: Server reports %s\n",p);
  12097. rc = -1;
  12098. }
  12099. http_set_code_reply(p);
  12100. } else {
  12101. if (!ckstrcmp(buf,"Connection:",11,0)) {
  12102. if ( ckindex("close",buf,11,0,0) != 0 )
  12103. closecon = 1;
  12104. } else if (!ckstrcmp(buf,"Content-Length:",15,0)) {
  12105. len = atoi(&buf[16]);
  12106. } else if (!ckstrcmp(buf,"Transfer-Encoding:",18,0)) {
  12107. if ( ckindex("chunked",buf,18,0,0) != 0 )
  12108. chunked = 1;
  12109. debug(F101,"http_post chunked","",chunked);
  12110. }
  12111. if (stdio)
  12112. printf("%s\n",buf);
  12113. }
  12114. i = 0;
  12115. } else {
  12116. i++;
  12117. }
  12118. }
  12119. if (ch < 0 && first) {
  12120. first--;
  12121. http_close();
  12122. http_reopen();
  12123. goto postopen;
  12124. }
  12125. if (http_fnd == 0) {
  12126. rc = -1;
  12127. closecon = 1;
  12128. goto postexit;
  12129. }
  12130. /* Any response data? */
  12131. if ( dest && dest[0] ) {
  12132. if (zopeno(ZOFILE,dest,NULL,NULL))
  12133. zfile = 1;
  12134. else
  12135. rc = -1;
  12136. }
  12137. if ( chunked ) {
  12138. while ((len = http_get_chunk_len()) > 0) {
  12139. while (len && (ch = http_inc(0)) >= 0) {
  12140. len--;
  12141. if ( zfile )
  12142. zchout(ZOFILE,(CHAR)ch);
  12143. if ( stdio )
  12144. conoc((CHAR)ch);
  12145. }
  12146. if ((ch = http_inc(0)) != CR)
  12147. break;
  12148. if ((ch = http_inc(0)) != LF)
  12149. break;
  12150. }
  12151. } else {
  12152. while (len && (ch = http_inc(0)) >= 0) {
  12153. len--;
  12154. if ( zfile )
  12155. zchout(ZOFILE,(CHAR)ch);
  12156. if ( stdio )
  12157. conoc((CHAR)ch);
  12158. }
  12159. }
  12160. if ( zfile )
  12161. zclose(ZOFILE);
  12162. if ( chunked ) { /* Parse Trailing Headers */
  12163. nullline = 0;
  12164. while (!nullline && (ch = http_inc(0)) >= 0 && i < HTTPBUFLEN) {
  12165. buf[i] = ch;
  12166. if ( buf[i] == 10 ) { /* found end of line */
  12167. if (i > 0 && buf[i-1] == 13)
  12168. i--;
  12169. if (i < 1)
  12170. nullline = 1;
  12171. buf[i] = '\0';
  12172. if (array && !nullline && hdcnt < HTTPHEADCNT)
  12173. makestr(&headers[hdcnt++],buf);
  12174. if (!ckstrcmp(buf,"Connection:",11,0)) {
  12175. if ( ckindex("close",buf,11,0,0) != 0 )
  12176. closecon = 1;
  12177. }
  12178. i = 0;
  12179. } else {
  12180. i++;
  12181. }
  12182. }
  12183. }
  12184. } else {
  12185. rc = -1;
  12186. }
  12187. postexit:
  12188. if (array)
  12189. http_mkarray(headers,hdcnt,array);
  12190. if (closecon)
  12191. http_close();
  12192. free(request);
  12193. for (i = 0; i < hdcnt; i++) {
  12194. if (headers[i])
  12195. free(headers[i]);
  12196. }
  12197. return(rc);
  12198. }
  12199. int
  12200. #ifdef CK_ANSIC
  12201. http_connect(int socket, char * agent, char ** hdrlist, char * user,
  12202. char * pwd, char array, char * host_port)
  12203. #else
  12204. http_connect(socket, agent, hdrlist, user, pwd, array, host_port)
  12205. int socket;
  12206. char * agent; char ** hdrlist; char * user;
  12207. char * pwd; char array; char * host_port;
  12208. #endif /* CK_ANSIC */
  12209. {
  12210. char * request=NULL;
  12211. int i, j, len = 0, hdcnt = 0, rc = 0;
  12212. int http_fnd = 0;
  12213. char buf[HTTPBUFLEN], *p, ch;
  12214. int nullline;
  12215. time_t mod_t;
  12216. time_t srv_t;
  12217. time_t local_t;
  12218. char passwd[64];
  12219. char b64in[128];
  12220. char b64out[256];
  12221. char * headers[HTTPHEADCNT];
  12222. int connected = 0;
  12223. tcp_http_proxy_errno = 0;
  12224. if (socket == -1)
  12225. return(-1);
  12226. if (array) {
  12227. for (i = 0; i < HTTPHEADCNT; i++)
  12228. headers[i] = NULL;
  12229. }
  12230. /* Compute length of request header */
  12231. len = 12; /* CONNECT */
  12232. len += strlen(HTTP_VERSION);
  12233. len += strlen(host_port);
  12234. len += (int) strlen(http_host_port) + 8;
  12235. len += 16;
  12236. len += strlen("Proxy-Connection: Keep-Alive\r\n");
  12237. if ( hdrlist ) {
  12238. for (i = 0; hdrlist[i]; i++)
  12239. len += strlen(hdrlist[i]) + 2;
  12240. }
  12241. if (agent && agent[0])
  12242. len += 13 + strlen(agent);
  12243. if (user && user[0]) {
  12244. if (!pwd) {
  12245. readpass("Password: ",passwd,64);
  12246. pwd = passwd;
  12247. }
  12248. ckmakmsg(b64in,sizeof(b64in),user,":",pwd,NULL);
  12249. j = b8tob64(b64in,strlen(b64in),b64out,256);
  12250. memset(pwd,0,strlen(pwd));
  12251. if (j < 0)
  12252. return(-1);
  12253. b64out[j] = '\0';
  12254. len += j + 72;
  12255. }
  12256. len += 32; /* Date: */
  12257. len += 3; /* blank line + null */
  12258. request = malloc(len);
  12259. if (!request)
  12260. return(-1);
  12261. sprintf(request,"CONNECT %s %s\r\n",host_port,HTTP_VERSION);
  12262. ckstrncat(request,"Date: ",len);
  12263. #ifdef CMDATE2TM
  12264. ckstrncat(request,http_now(),len);
  12265. #else
  12266. strcat(request,...);
  12267. #endif /* CMDATE2TM */
  12268. ckstrncat(request,"\r\n",len);
  12269. ckstrncat(request,"Host: ", len);
  12270. ckstrncat(request,http_host_port, len);
  12271. ckstrncat(request,"\r\n",len);
  12272. if (agent && agent[0]) {
  12273. ckstrncat(request,"User-agent: ",len);
  12274. ckstrncat(request,agent,len);
  12275. ckstrncat(request,"\r\n",len);
  12276. }
  12277. if (user && user[0]) {
  12278. ckstrncat(request,"Proxy-authorization: Basic ",len);
  12279. ckstrncat(request,b64out,len);
  12280. ckstrncat(request,"\r\n",len);
  12281. ckstrncat(request,"Extension: Security/Remote-Passphrase\r\n",len);
  12282. }
  12283. ckstrncat(request,"Proxy-Connection: Keep-Alive\r\n",len);
  12284. if ( hdrlist ) {
  12285. for (i = 0; hdrlist[i]; i++) {
  12286. ckstrncat(request,hdrlist[i],len);
  12287. ckstrncat(request,"\r\n",len);
  12288. }
  12289. }
  12290. ckstrncat(request,"\r\n",len);
  12291. len = strlen(request);
  12292. #ifdef TCPIPLIB
  12293. /* Send request */
  12294. if (socket_write(socket,(CHAR *)request,strlen(request)) < 0) {
  12295. rc = -1;
  12296. goto connexit;
  12297. }
  12298. #else
  12299. if (write(socket,(CHAR *)request,strlen(request)) < 0) { /* Send request */
  12300. rc = -1;
  12301. goto connexit;
  12302. }
  12303. #endif /* TCPIPLIB */
  12304. /* Process the response headers */
  12305. local_t = time(NULL);
  12306. nullline = 0;
  12307. i = 0;
  12308. while (!nullline &&
  12309. #ifdef TCPIPLIB
  12310. (socket_read(socket,&ch,1) == 1) &&
  12311. #else
  12312. (read(socket,&ch,1) == 1) &&
  12313. #endif /* TCPIPLIB */
  12314. i < HTTPBUFLEN) {
  12315. buf[i] = ch;
  12316. if (buf[i] == 10) { /* found end of line */
  12317. if (i > 0 && buf[i-1] == 13)
  12318. i--;
  12319. if (i < 1)
  12320. nullline = 1;
  12321. buf[i] = '\0';
  12322. if (array && !nullline && hdcnt < HTTPHEADCNT)
  12323. makestr(&headers[hdcnt++],buf);
  12324. if (!ckstrcmp(buf,"HTTP",4,0)) {
  12325. http_fnd = 1;
  12326. j = ckindex(" ",buf,0,0,0);
  12327. p = &buf[j];
  12328. while (isspace(*p))
  12329. p++;
  12330. tcp_http_proxy_errno = atoi(p);
  12331. switch (p[0]) {
  12332. case '1': /* Informational message */
  12333. break;
  12334. case '2': /* Success */
  12335. connected = 1;
  12336. break;
  12337. case '3': /* Redirection */
  12338. case '4': /* Client failure */
  12339. case '5': /* Server failure */
  12340. default: /* Unknown */
  12341. if (!quiet)
  12342. printf("Failure: Server reports %s\n",p);
  12343. rc = -1;
  12344. }
  12345. http_set_code_reply(p);
  12346. } else {
  12347. printf("%s\n",buf);
  12348. }
  12349. i = 0;
  12350. } else {
  12351. i++;
  12352. }
  12353. }
  12354. if ( http_fnd == 0 )
  12355. rc = -1;
  12356. if (array)
  12357. http_mkarray(headers,hdcnt,array);
  12358. connexit:
  12359. if ( !connected ) {
  12360. if ( socket == ttyfd ) {
  12361. ttclos(0);
  12362. }
  12363. else if ( socket == httpfd ) {
  12364. http_close();
  12365. }
  12366. }
  12367. free(request);
  12368. for (i = 0; i < hdcnt; i++) {
  12369. if (headers[i])
  12370. free(headers[i]);
  12371. }
  12372. return(rc);
  12373. }
  12374. #endif /* NOHTTP */
  12375. #ifdef CK_DNS_SRV
  12376. #define INCR_CHECK(x,y) x += y; if (x > size + answer.bytes) goto dnsout
  12377. #define CHECK(x,y) if (x + y > size + answer.bytes) goto dnsout
  12378. #define NTOHSP(x,y) x[0] << 8 | x[1]; x += y
  12379. #ifndef CKQUERYTYPE
  12380. #ifdef UNIXWARE
  12381. #ifndef UW7
  12382. #define CKQUERYTYPE CHAR
  12383. #endif /* UW7 */
  12384. #endif /* UNIXWARE */
  12385. #endif /* CKQUERYTYPE */
  12386. #ifndef CKQUERYTYPE
  12387. #define CKQUERYTYPE char
  12388. #endif /* CKQUERYTYPE */
  12389. /* 1 is success, 0 is failure */
  12390. int
  12391. locate_srv_dns(host, service, protocol, addr_pp, naddrs)
  12392. char *host;
  12393. char *service;
  12394. char *protocol;
  12395. struct sockaddr **addr_pp;
  12396. int *naddrs;
  12397. {
  12398. int nout, j, count;
  12399. union {
  12400. unsigned char bytes[2048];
  12401. HEADER hdr;
  12402. } answer;
  12403. unsigned char *p=NULL;
  12404. CKQUERYTYPE query[MAX_DNS_NAMELEN];
  12405. #ifdef CK_ANSIC
  12406. const char * h;
  12407. #else
  12408. char * h;
  12409. #endif /* CK_ANSIC */
  12410. struct sockaddr *addr = NULL;
  12411. struct sockaddr_in *sin = NULL;
  12412. struct hostent *hp = NULL;
  12413. int type, class;
  12414. int priority, weight, size, len, numanswers, numqueries, rdlen;
  12415. unsigned short port;
  12416. #ifdef CK_ANSIC
  12417. const
  12418. #endif /* CK_ANSIC */
  12419. int hdrsize = sizeof(HEADER);
  12420. struct srv_dns_entry {
  12421. struct srv_dns_entry *next;
  12422. int priority;
  12423. int weight;
  12424. unsigned short port;
  12425. char *host;
  12426. };
  12427. struct srv_dns_entry *head = NULL;
  12428. struct srv_dns_entry *srv = NULL, *entry = NULL;
  12429. char * s = NULL;
  12430. nout = 0;
  12431. addr = (struct sockaddr *) malloc(sizeof(struct sockaddr));
  12432. if (addr == NULL)
  12433. return 0;
  12434. count = 1;
  12435. /*
  12436. * First build a query of the form:
  12437. *
  12438. * service.protocol.host
  12439. *
  12440. * which will most likely be something like:
  12441. *
  12442. * _telnet._tcp.host
  12443. *
  12444. */
  12445. if (((int)strlen(service) + strlen(protocol) + strlen(host) + 5)
  12446. > MAX_DNS_NAMELEN
  12447. )
  12448. goto dnsout;
  12449. /* Realm names don't (normally) end with ".", but if the query
  12450. doesn't end with "." and doesn't get an answer as is, the
  12451. resolv code will try appending the local domain. Since the
  12452. realm names are absolutes, let's stop that.
  12453. But only if a name has been specified. If we are performing
  12454. a search on the prefix alone then the intention is to allow
  12455. the local domain or domain search lists to be expanded.
  12456. */
  12457. h = host + strlen (host);
  12458. ckmakxmsg(query, sizeof(query), "_",service,"._",protocol,".", host,
  12459. ((h > host) && (h[-1] != '.')?".":NULL),
  12460. NULL,NULL,NULL,NULL,NULL);
  12461. size = res_search(query, C_IN, T_SRV, answer.bytes, sizeof(answer.bytes));
  12462. if (size < hdrsize)
  12463. goto dnsout;
  12464. /* We got a reply - See how many answers it contains. */
  12465. p = answer.bytes;
  12466. numqueries = ntohs(answer.hdr.qdcount);
  12467. numanswers = ntohs(answer.hdr.ancount);
  12468. p += sizeof(HEADER);
  12469. /*
  12470. * We need to skip over all of the questions, so we have to iterate
  12471. * over every query record. dn_expand() is able to tell us the size
  12472. * of compressed DNS names, so we use it.
  12473. */
  12474. while (numqueries--) {
  12475. len = dn_expand(answer.bytes,answer.bytes+size,p,query,sizeof(query));
  12476. if (len < 0)
  12477. goto dnsout;
  12478. INCR_CHECK(p, len + 4);
  12479. }
  12480. /*
  12481. * We're now pointing at the answer records. Only process them if
  12482. * they're actually T_SRV records (they might be CNAME records,
  12483. * for instance).
  12484. *
  12485. * But in a DNS reply, if you get a CNAME you always get the associated
  12486. * "real" RR for that CNAME. RFC 1034, 3.6.2:
  12487. *
  12488. * CNAME RRs cause special action in DNS software. When a name server
  12489. * fails to find a desired RR in the resource set associated with the
  12490. * domain name, it checks to see if the resource set consists of a CNAME
  12491. * record with a matching class. If so, the name server includes the CNAME
  12492. * record in the response and restarts the query at the domain name
  12493. * specified in the data field of the CNAME record. The one exception to
  12494. * this rule is that queries which match the CNAME type are not restarted.
  12495. *
  12496. * In other words, CNAMEs do not need to be expanded by the client.
  12497. */
  12498. while (numanswers--) {
  12499. /* First is the name; use dn_expand() to get the compressed size. */
  12500. len = dn_expand(answer.bytes,answer.bytes+size,p,query,sizeof(query));
  12501. if (len < 0)
  12502. goto dnsout;
  12503. INCR_CHECK(p, len);
  12504. CHECK(p,2); /* Query type */
  12505. type = NTOHSP(p,2);
  12506. CHECK(p, 6); /* Query class */
  12507. class = NTOHSP(p,6); /* Also skip over 4-byte TTL */
  12508. CHECK(p,2); /* Record data length */
  12509. rdlen = NTOHSP(p,2);
  12510. /*
  12511. * If this is an SRV record, process it. Record format is:
  12512. *
  12513. * Priority
  12514. * Weight
  12515. * Port
  12516. * Server name
  12517. */
  12518. if (class == C_IN && type == T_SRV) {
  12519. CHECK(p,2);
  12520. priority = NTOHSP(p,2);
  12521. CHECK(p, 2);
  12522. weight = NTOHSP(p,2);
  12523. CHECK(p, 2);
  12524. port = NTOHSP(p,2);
  12525. len = dn_expand(answer.
  12526. bytes,
  12527. answer.bytes + size,
  12528. p,
  12529. query,
  12530. sizeof(query)
  12531. );
  12532. if (len < 0)
  12533. goto dnsout;
  12534. INCR_CHECK(p, len);
  12535. /*
  12536. * We got everything. Insert it into our list, but make sure
  12537. * it's in the right order. Right now we don't do anything
  12538. * with the weight field
  12539. */
  12540. srv = (struct srv_dns_entry *)malloc(sizeof(struct srv_dns_entry));
  12541. if (srv == NULL)
  12542. goto dnsout;
  12543. srv->priority = priority;
  12544. srv->weight = weight;
  12545. srv->port = port;
  12546. makestr(&s,(char *)query); /* strdup() is not portable */
  12547. srv->host = s;
  12548. if (head == NULL || head->priority > srv->priority) {
  12549. srv->next = head;
  12550. head = srv;
  12551. } else
  12552. /*
  12553. * Confusing. Insert an entry into this spot only if:
  12554. * . The next person has a higher priority (lower
  12555. * priorities are preferred), or:
  12556. * . There is no next entry (we're at the end)
  12557. */
  12558. for (entry = head; entry != NULL; entry = entry->next)
  12559. if ((entry->next &&
  12560. entry->next->priority > srv->priority) ||
  12561. entry->next == NULL) {
  12562. srv->next = entry->next;
  12563. entry->next = srv;
  12564. break;
  12565. }
  12566. } else
  12567. INCR_CHECK(p, rdlen);
  12568. }
  12569. /*
  12570. * Now we've got a linked list of entries sorted by priority.
  12571. * Start looking up A records and returning addresses.
  12572. */
  12573. if (head == NULL)
  12574. goto dnsout;
  12575. for (entry = head; entry != NULL; entry = entry->next) {
  12576. hp = gethostbyname(entry->host);
  12577. if (hp != 0) {
  12578. /* Watch out - memset() and memcpy() are not portable... */
  12579. switch (hp->h_addrtype) {
  12580. case AF_INET:
  12581. for (j = 0; hp->h_addr_list[j]; j++) {
  12582. sin = (struct sockaddr_in *) &addr[nout++];
  12583. memset ((char *) sin, 0, sizeof (struct sockaddr));
  12584. sin->sin_family = hp->h_addrtype;
  12585. sin->sin_port = htons(entry->port);
  12586. memcpy((char *) &sin->sin_addr,
  12587. (char *) hp->h_addr_list[j],
  12588. sizeof(struct in_addr)); /* safe */
  12589. if (nout + 1 >= count) {
  12590. count += 5;
  12591. addr = (struct sockaddr *)
  12592. realloc((char *) addr,
  12593. sizeof(struct sockaddr) * count);
  12594. if (!addr)
  12595. goto dnsout;
  12596. }
  12597. }
  12598. break;
  12599. default:
  12600. break;
  12601. }
  12602. }
  12603. }
  12604. for (entry = head; entry != NULL;) {
  12605. free(entry->host);
  12606. entry->host = NULL;
  12607. srv = entry;
  12608. entry = entry->next;
  12609. free(srv);
  12610. srv = NULL;
  12611. }
  12612. dnsout:
  12613. if (srv)
  12614. free(srv);
  12615. if (nout == 0) { /* No good servers */
  12616. if (addr)
  12617. free(addr);
  12618. return 0;
  12619. }
  12620. *addr_pp = addr;
  12621. *naddrs = nout;
  12622. return 1;
  12623. }
  12624. #undef INCR_CHECK
  12625. #undef CHECK
  12626. #undef NTOHSP
  12627. #define INCR_CHECK(x, y) x += y; if (x > size + answer.bytes) \
  12628. return 0
  12629. #define CHECK(x, y) if (x + y > size + answer.bytes) \
  12630. return 0
  12631. #define NTOHSP(x, y) x[0] << 8 | x[1]; x += y
  12632. int
  12633. locate_txt_rr(prefix, name, retstr)
  12634. char *prefix, *name;
  12635. char **retstr;
  12636. {
  12637. union {
  12638. unsigned char bytes[2048];
  12639. HEADER hdr;
  12640. } answer;
  12641. unsigned char *p;
  12642. char host[MAX_DNS_NAMELEN], *h;
  12643. int size;
  12644. int type, class, numanswers, numqueries, rdlen, len;
  12645. /*
  12646. * Form our query, and send it via DNS
  12647. */
  12648. if (name == NULL || name[0] == '\0') {
  12649. strcpy(host,prefix);
  12650. } else {
  12651. if ( strlen(prefix) + strlen(name) + 3 > MAX_DNS_NAMELEN )
  12652. return 0;
  12653. /* Realm names don't (normally) end with ".", but if the query
  12654. doesn't end with "." and doesn't get an answer as is, the
  12655. resolv code will try appending the local domain. Since the
  12656. realm names are absolutes, let's stop that.
  12657. But only if a name has been specified. If we are performing
  12658. a search on the prefix alone then the intention is to allow
  12659. the local domain or domain search lists to be expanded.
  12660. */
  12661. h = host + strlen (host);
  12662. ckmakmsg(host,sizeof(host),prefix, ".", name,
  12663. ((h > host) && (h[-1] != '.'))?".":NULL);
  12664. }
  12665. size = res_search(host, C_IN, T_TXT, answer.bytes, sizeof(answer.bytes));
  12666. if (size < 0)
  12667. return 0;
  12668. p = answer.bytes;
  12669. numqueries = ntohs(answer.hdr.qdcount);
  12670. numanswers = ntohs(answer.hdr.ancount);
  12671. p += sizeof(HEADER);
  12672. /*
  12673. * We need to skip over the questions before we can get to the answers,
  12674. * which means we have to iterate over every query record. We use
  12675. * dn_expand to tell us how long each compressed name is.
  12676. */
  12677. while (numqueries--) {
  12678. len = dn_expand(answer.bytes, answer.bytes + size, p, host,
  12679. sizeof(host));
  12680. if (len < 0)
  12681. return 0;
  12682. INCR_CHECK(p, len + 4); /* Name plus type plus class */
  12683. }
  12684. /*
  12685. * We're now pointing at the answer records. Process the first
  12686. * TXT record we find.
  12687. */
  12688. while (numanswers--) {
  12689. /* First the name; use dn_expand to get the compressed size */
  12690. len = dn_expand(answer.bytes, answer.bytes + size, p,
  12691. host, sizeof(host));
  12692. if (len < 0)
  12693. return 0;
  12694. INCR_CHECK(p, len);
  12695. /* Next is the query type */
  12696. CHECK(p, 2);
  12697. type = NTOHSP(p,2);
  12698. /* Next is the query class; also skip over 4 byte TTL */
  12699. CHECK(p,6);
  12700. class = NTOHSP(p,6);
  12701. /* Record data length - make sure we aren't truncated */
  12702. CHECK(p,2);
  12703. rdlen = NTOHSP(p,2);
  12704. if (p + rdlen > answer.bytes + size)
  12705. return 0;
  12706. /*
  12707. * If this is a TXT record, return the string. Note that the
  12708. * string has a 1-byte length in the front
  12709. */
  12710. /* XXX What about flagging multiple TXT records as an error? */
  12711. if (class == C_IN && type == T_TXT) {
  12712. len = *p++;
  12713. if (p + len > answer.bytes + size)
  12714. return 0;
  12715. *retstr = malloc(len + 1);
  12716. if (*retstr == NULL)
  12717. return ENOMEM;
  12718. strncpy(*retstr, (char *) p, len);
  12719. (*retstr)[len] = '\0';
  12720. /* Avoid a common error. */
  12721. if ( (*retstr)[len-1] == '.' )
  12722. (*retstr)[len-1] = '\0';
  12723. return 1;
  12724. }
  12725. }
  12726. return 0;
  12727. }
  12728. #undef INCR_CHECK
  12729. #undef CHECK
  12730. #undef NTOHSP
  12731. #endif /* CK_DNS_SRV */
  12732. #ifdef TNCODE
  12733. #ifdef CK_FORWARD_X
  12734. #ifdef UNIX
  12735. #include <sys/un.h>
  12736. #define FWDX_UNIX_SOCK
  12737. #ifndef AF_LOCAL
  12738. #define AF_LOCAL AF_UNIX
  12739. #endif
  12740. #ifndef PF_LOCAL
  12741. #define PF_LOCAL PF_UNIX
  12742. #endif
  12743. #ifndef SUN_LEN
  12744. /* Evaluate to actual length of the `sockaddr_un' structure. */
  12745. #define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
  12746. + strlen ((ptr)->sun_path))
  12747. #endif
  12748. #endif /* UNIX */
  12749. int
  12750. fwdx_create_listen_socket(screen) int screen; {
  12751. #ifdef NOPUTENV
  12752. return(-1);
  12753. #else /* NOPUTENV */
  12754. struct sockaddr_in saddr;
  12755. int display, port, sock=-1, i;
  12756. static char env[512];
  12757. /*
  12758. * X Windows Servers support multiple displays by listening on
  12759. * one socket per display. Display 0 is port 6000; Display 1 is
  12760. * port 6001; etc.
  12761. *
  12762. * We start by trying to open port 6001 so that display 0 is
  12763. * reserved for the local X Windows Server.
  12764. */
  12765. for ( display=1; display < 1000 ; display++ ) {
  12766. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  12767. debug(F111,"fwdx_create_listen_socket()","socket() < 0",sock);
  12768. return(-1);
  12769. }
  12770. port = 6000 + display;
  12771. bzero((char *)&saddr, sizeof(saddr));
  12772. saddr.sin_family = AF_INET;
  12773. saddr.sin_addr.s_addr = inet_addr(myipaddr);
  12774. saddr.sin_port = htons(port);
  12775. if (bind(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
  12776. i = errno; /* Save error code */
  12777. #ifdef TCPIPLIB
  12778. socket_close(sock);
  12779. #else /* TCPIPLIB */
  12780. close(sock);
  12781. #endif /* TCPIPLIB */
  12782. sock = -1;
  12783. debug(F110,"fwdx_create_listen_socket()","bind() < 0",0);
  12784. continue;
  12785. }
  12786. debug(F100,"fdwx_create_listen_socket() bind OK","",0);
  12787. break;
  12788. }
  12789. if ( display > 1000 ) {
  12790. debug(F100,"fwdx_create_listen_socket() Out of Displays","",0);
  12791. return(-1);
  12792. }
  12793. if (listen(sock, 5) < 0) {
  12794. i = errno; /* Save error code */
  12795. #ifdef TCPIPLIB
  12796. socket_close(sock);
  12797. #else /* TCPIPLIB */
  12798. close(sock);
  12799. #endif /* TCPIPLIB */
  12800. debug(F101,"fdwx_create_listen_socket() listen() errno","",errno);
  12801. return(-1);
  12802. }
  12803. debug(F100,"fwdx_create_listen_socket() listen OK","",0);
  12804. TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = sock;
  12805. if (!myipaddr[0])
  12806. getlocalipaddr();
  12807. if ( myipaddr[0] )
  12808. ckmakxmsg(env,sizeof(env),"DISPLAY=",myipaddr,":",
  12809. ckuitoa(display),":",ckuitoa(screen),
  12810. NULL,NULL,NULL,NULL,NULL,NULL);
  12811. else
  12812. ckmakmsg(env,sizeof(env),"DISPLAY=",ckuitoa(display),":",
  12813. ckuitoa(screen));
  12814. putenv(env);
  12815. return(0);
  12816. #endif /* NOPUTENV */
  12817. }
  12818. int
  12819. fwdx_open_client_channel(channel) int channel; {
  12820. char * env;
  12821. struct sockaddr_in saddr;
  12822. #ifdef FWDX_UNIX_SOCK
  12823. struct sockaddr_un saddr_un = { AF_LOCAL };
  12824. #endif /* FWDX_UNIX_SOCK */
  12825. int colon, dot, display, port, sock, i, screen;
  12826. int family;
  12827. char buf[256], * host=NULL, * rest=NULL;
  12828. #ifdef TCP_NODELAY
  12829. int on=1;
  12830. #endif /* TCP_NODELAY */
  12831. debug(F111,"fwdx_create_client_channel()","channel",channel);
  12832. for ( i=0; i<MAXFWDX ; i++ ) {
  12833. if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel) {
  12834. /* Already open */
  12835. debug(F110,"fwdx_create_client_channel()","already open",0);
  12836. return(0);
  12837. }
  12838. }
  12839. env = getenv("DISPLAY");
  12840. if ( !env )
  12841. env = (char *)tn_get_display();
  12842. if ( env )
  12843. ckstrncpy(buf,env,256);
  12844. else
  12845. ckstrncpy(buf,"127.0.0.1:0.0",256);
  12846. bzero((char *)&saddr,sizeof(saddr));
  12847. saddr.sin_family = AF_INET;
  12848. if (!fwdx_parse_displayname(buf,
  12849. &family,
  12850. &host,
  12851. &display,
  12852. &screen,
  12853. &rest
  12854. )
  12855. ) {
  12856. if ( host ) free(host);
  12857. if ( rest ) free(rest);
  12858. return(0);
  12859. }
  12860. if (rest) free(rest);
  12861. #ifndef FWDX_UNIX_SOCK
  12862. /* if $DISPLAY indicates use of unix domain sockets, but we don't support it,
  12863. * we change things to use inet sockets on the ip loopback interface instead,
  12864. * and hope that it works.
  12865. */
  12866. if (family == FamilyLocal) {
  12867. debug(F100,"fwdx_create_client_channel() FamilyLocal","",0);
  12868. family = FamilyInternet;
  12869. if (host) free(host);
  12870. if (host = malloc(strlen("localhost") + 1))
  12871. strcpy(host, "localhost");
  12872. else {
  12873. return(-1);
  12874. }
  12875. }
  12876. #else /* FWDX_UNIX_SOCK */
  12877. if (family == FamilyLocal) {
  12878. if (host) free(host);
  12879. sock = socket(PF_LOCAL, SOCK_STREAM, 0);
  12880. if (sock < 0)
  12881. return(-1);
  12882. ckmakmsg(buf,sizeof(buf),"/tmp/.X11-unix/X",ckitoa(display),NULL,NULL);
  12883. strncpy(saddr_un.sun_path, buf, sizeof(saddr_un.sun_path));
  12884. if (connect(sock,(struct sockaddr *)&saddr_un, SUN_LEN(&saddr_un)) < 0)
  12885. return(-1);
  12886. } else
  12887. #endif /* FWDX_UNIX_SOCK */
  12888. {
  12889. /* Otherwise, we are assuming FamilyInternet */
  12890. if (host) {
  12891. ckstrncpy(buf,host,sizeof(buf));
  12892. free(host);
  12893. } else
  12894. ckstrncpy(buf,myipaddr,sizeof(buf));
  12895. debug(F111,"fwdx_create_client_channel()","display",display);
  12896. port = 6000 + display;
  12897. saddr.sin_port = htons(port);
  12898. debug(F110,"fwdx_create_client_channel() ip-address",buf,0);
  12899. saddr.sin_addr.s_addr = inet_addr(buf);
  12900. if ( saddr.sin_addr.s_addr == (unsigned long) -1
  12901. #ifdef INADDR_NONE
  12902. || saddr.sin_addr.s_addr == INADDR_NONE
  12903. #endif /* INADDR_NONE */
  12904. )
  12905. {
  12906. struct hostent *host;
  12907. host = gethostbyname(buf);
  12908. if ( host == NULL )
  12909. return(-1);
  12910. host = ck_copyhostent(host);
  12911. #ifdef HADDRLIST
  12912. #ifdef h_addr
  12913. /* This is for trying multiple IP addresses - see <netdb.h> */
  12914. if (!(host->h_addr_list))
  12915. return(-1);
  12916. bcopy(host->h_addr_list[0],
  12917. (caddr_t)&saddr.sin_addr,
  12918. host->h_length
  12919. );
  12920. #else
  12921. bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
  12922. #endif /* h_addr */
  12923. #else /* HADDRLIST */
  12924. bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
  12925. #endif /* HADDRLIST */
  12926. }
  12927. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  12928. debug(F111,"fwdx_create_client_channel()","socket() < 0",sock);
  12929. return(-1);
  12930. }
  12931. if ( connect(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
  12932. debug(F110,"fwdx_create_client_channel()","connect() failed",0);
  12933. #ifdef TCPIPLIB
  12934. socket_close(sock);
  12935. #else /* TCPIPLIB */
  12936. close(sock);
  12937. #endif /* TCPIPLIB */
  12938. return(-1);
  12939. }
  12940. #ifdef TCP_NODELAY
  12941. setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char *)&on,sizeof(on));
  12942. #endif /* TCP_NODELAY */
  12943. }
  12944. for (i = 0; i < MAXFWDX; i++) {
  12945. if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == -1) {
  12946. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd = sock;
  12947. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id = channel;
  12948. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 1;
  12949. debug(F111,"fwdx_create_client_channel()","socket",sock);
  12950. return(0);
  12951. }
  12952. }
  12953. return(-1);
  12954. }
  12955. int
  12956. fwdx_server_avail() {
  12957. char * env;
  12958. struct sockaddr_in saddr;
  12959. #ifdef FWDX_UNIX_SOCK
  12960. struct sockaddr_un saddr_un = { AF_LOCAL };
  12961. #endif /* FWDX_UNIX_SOCK */
  12962. int colon, dot, display, port, sock, i, screen;
  12963. char buf[256], *host=NULL, *rest=NULL;
  12964. #ifdef TCP_NODELAY
  12965. int on=1;
  12966. #endif /* TCP_NODELAY */
  12967. int family;
  12968. env = getenv("DISPLAY");
  12969. if ( !env )
  12970. env = (char *)tn_get_display();
  12971. if ( env )
  12972. ckstrncpy(buf,env,256);
  12973. else
  12974. ckstrncpy(buf,"127.0.0.1:0.0",256);
  12975. bzero((char *)&saddr,sizeof(saddr));
  12976. saddr.sin_family = AF_INET;
  12977. if (!fwdx_parse_displayname(buf,&family,&host,&display,&screen,&rest)) {
  12978. if ( host ) free(host);
  12979. if ( rest ) free(rest);
  12980. return(0);
  12981. }
  12982. if (rest) free(rest);
  12983. #ifndef FWDX_UNIX_SOCK
  12984. /* if $DISPLAY indicates use of unix domain sockets, but we don't support it,
  12985. * we change things to use inet sockets on the ip loopback interface instead,
  12986. * and hope that it works.
  12987. */
  12988. if (family == FamilyLocal) {
  12989. family = FamilyInternet;
  12990. if (host) free(host);
  12991. if (host = malloc(strlen("localhost") + 1))
  12992. strcpy(host, "localhost");
  12993. else {
  12994. return(-1);
  12995. }
  12996. }
  12997. #else /* FWDX_UNIX_SOCK */
  12998. if (family == FamilyLocal) {
  12999. debug(F100,"fwdx_server_avail() FamilyLocal","",0);
  13000. if (host) free(host);
  13001. sock = socket(PF_LOCAL, SOCK_STREAM, 0);
  13002. if (sock < 0)
  13003. return(0);
  13004. ckmakmsg(buf,sizeof(buf),"/tmp/.X11-unix/X",ckitoa(display),NULL,NULL);
  13005. strncpy(saddr_un.sun_path, buf, sizeof(saddr_un.sun_path));
  13006. if (connect(sock,(struct sockaddr *)&saddr_un,SUN_LEN(&saddr_un)) < 0)
  13007. return(0);
  13008. close(sock);
  13009. return(1);
  13010. }
  13011. #endif /* FWDX_UNIX_SOCK */
  13012. /* Otherwise, we are assuming FamilyInternet */
  13013. if (host) {
  13014. ckstrncpy(buf,host,sizeof(buf));
  13015. free(host);
  13016. } else
  13017. ckstrncpy(buf,myipaddr,sizeof(buf));
  13018. debug(F111,"fwdx_server_avail()","display",display);
  13019. port = 6000 + display;
  13020. saddr.sin_port = htons(port);
  13021. debug(F110,"fwdx_server_avail() ip-address",buf,0);
  13022. saddr.sin_addr.s_addr = inet_addr(buf);
  13023. if ( saddr.sin_addr.s_addr == (unsigned long) -1
  13024. #ifdef INADDR_NONE
  13025. || saddr.sin_addr.s_addr == INADDR_NONE
  13026. #endif /* INADDR_NONE */
  13027. )
  13028. {
  13029. struct hostent *host;
  13030. host = gethostbyname(buf);
  13031. if ( host == NULL ) {
  13032. debug(F110,"fwdx_server_avail() gethostbyname() failed",
  13033. myipaddr,0);
  13034. return(-1);
  13035. }
  13036. host = ck_copyhostent(host);
  13037. #ifdef HADDRLIST
  13038. #ifdef h_addr
  13039. /* This is for trying multiple IP addresses - see <netdb.h> */
  13040. if (!(host->h_addr_list))
  13041. return(-1);
  13042. bcopy(host->h_addr_list[0],
  13043. (caddr_t)&saddr.sin_addr,
  13044. host->h_length
  13045. );
  13046. #else
  13047. bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
  13048. #endif /* h_addr */
  13049. #else /* HADDRLIST */
  13050. bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
  13051. #endif /* HADDRLIST */
  13052. }
  13053. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  13054. debug(F111,"fwdx_server_avail()","socket() < 0",sock);
  13055. return(0);
  13056. }
  13057. if ( connect(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
  13058. debug(F110,"fwdx_server_avail()","connect() failed",0);
  13059. #ifdef TCPIPLIB
  13060. socket_close(sock);
  13061. #else /* TCPIPLIB */
  13062. close(sock);
  13063. #endif /* TCPIPLIB */
  13064. return(0);
  13065. }
  13066. #ifdef TCPIPLIB
  13067. socket_close(sock);
  13068. #else /* TCPIPLIB */
  13069. close(sock);
  13070. #endif /* TCPIPLIB */
  13071. return(1);
  13072. }
  13073. int
  13074. fwdx_open_server_channel() {
  13075. int sock, ready_to_accept, sock2,channel,i;
  13076. #ifdef TCP_NODELAY
  13077. int on=1;
  13078. #endif /* TCP_NODELAY */
  13079. #ifdef UCX50
  13080. static u_int saddrlen;
  13081. #else
  13082. static SOCKOPT_T saddrlen;
  13083. #endif /* UCX50 */
  13084. struct sockaddr_in saddr;
  13085. char sb[8];
  13086. extern char tn_msg[];
  13087. #ifdef BSDSELECT
  13088. fd_set rfds;
  13089. struct timeval tv;
  13090. #else
  13091. #ifdef BELLSELCT
  13092. fd_set rfds;
  13093. #else
  13094. fd_set rfds;
  13095. struct timeval {
  13096. long tv_sec;
  13097. long tv_usec;
  13098. } tv;
  13099. #endif /* BELLSELECT */
  13100. #endif /* BSDSELECT */
  13101. unsigned short nchannel;
  13102. unsigned char * p;
  13103. sock = TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket;
  13104. try_again:
  13105. #ifdef BSDSELECT
  13106. tv.tv_sec = tv.tv_usec = 0L;
  13107. tv.tv_usec = 50;
  13108. FD_ZERO(&rfds);
  13109. FD_SET(sock, &rfds);
  13110. ready_to_accept =
  13111. ((select(FD_SETSIZE,
  13112. #ifdef HPUX
  13113. #ifdef HPUX1010
  13114. (fd_set *)
  13115. #else
  13116. (int *)
  13117. #endif /* HPUX1010 */
  13118. #else
  13119. #ifdef __DECC
  13120. (fd_set *)
  13121. #endif /* __DECC */
  13122. #endif /* HPUX */
  13123. &rfds, NULL, NULL, &tv) > 0) &&
  13124. FD_ISSET(sock, &rfds));
  13125. #else /* BSDSELECT */
  13126. #ifdef IBMSELECT
  13127. ready_to_accept = (select(&sock, 1, 0, 0, 50) == 1);
  13128. #else
  13129. #ifdef BELLSELECT
  13130. FD_ZERO(rfds);
  13131. FD_SET(sock, rfds);
  13132. ready_to_accept =
  13133. ((select(128, rfds, NULL, NULL, 50) > 0) &&
  13134. FD_ISSET(sock, rfds));
  13135. #else
  13136. /* Try this - what's the worst that can happen... */
  13137. tv.tv_sec = tv.tv_usec = 0L;
  13138. tv.tv_usec = 50;
  13139. FD_ZERO(&rfds);
  13140. FD_SET(sock, &rfds);
  13141. ready_to_accept =
  13142. ((select(FD_SETSIZE,
  13143. (fd_set *) &rfds, NULL, NULL, &tv) > 0) &&
  13144. FD_ISSET(sock, &rfds));
  13145. #endif /* BELLSELECT */
  13146. #endif /* IBMSELECT */
  13147. #endif /* BSDSELECT */
  13148. if ( !ready_to_accept )
  13149. return(0);
  13150. if ((sock2 = accept(sock,(struct sockaddr *)&saddr,&saddrlen)) < 0) {
  13151. int i = errno; /* save error code */
  13152. debug(F101,"tcpsrv_open accept errno","",i);
  13153. return(-1);
  13154. }
  13155. /*
  13156. * Now we have the open socket. We must now find a channel to store
  13157. * it in, and then notify the client.
  13158. */
  13159. for ( channel=0;channel<MAXFWDX;channel++ ) {
  13160. if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].fd == -1 )
  13161. break;
  13162. }
  13163. if ( channel == MAXFWDX ) {
  13164. #ifdef TCPIPLIB
  13165. socket_close(sock2);
  13166. #else /* TCPIPLIB */
  13167. close(sock2);
  13168. #endif /* TCPIPLIB */
  13169. return(-1);
  13170. }
  13171. if ( fwdx_send_open(channel) < 0 ) {
  13172. #ifdef TCPIPLIB
  13173. socket_close(sock2);
  13174. #else /* TCPIPLIB */
  13175. close(sock2);
  13176. #endif /* TCPIPLIB */
  13177. }
  13178. #ifdef TCP_NODELAY
  13179. setsockopt(sock2,IPPROTO_TCP,TCP_NODELAY,(char *)&on,sizeof(on));
  13180. #endif /* TCP_NODELAY */
  13181. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].fd = sock2;
  13182. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].id = channel;
  13183. goto try_again;
  13184. return(0); /* never reached */
  13185. }
  13186. int
  13187. fwdx_close_channel(channel) int channel; {
  13188. int i,fd;
  13189. for ( i=0; i<MAXFWDX ; i++ ) {
  13190. if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel)
  13191. break;
  13192. }
  13193. if ( i == MAXFWDX )
  13194. return(-1);
  13195. fd = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd;
  13196. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd = -1;
  13197. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id = -1;
  13198. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
  13199. #ifdef TCPIPLIB
  13200. socket_close(fd);
  13201. #else /* TCPIPLIB */
  13202. close(fd);
  13203. #endif /* TCPIPLIB */
  13204. return(0);
  13205. }
  13206. int
  13207. fwdx_close_all() {
  13208. int x,fd;
  13209. debug(F111,"fwdx_close_all()",
  13210. "TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket",
  13211. TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket);
  13212. if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket != -1 ) {
  13213. #ifdef TCPIPLIB
  13214. socket_close(TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket);
  13215. #else /* TCPIPLIB */
  13216. close(TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket);
  13217. #endif /* TCPIPLIB */
  13218. TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
  13219. }
  13220. for (x = 0; x < MAXFWDX; x++) {
  13221. if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd != -1) {
  13222. fd = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd;
  13223. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
  13224. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
  13225. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
  13226. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
  13227. #ifdef TCPIPLIB
  13228. socket_close(fd);
  13229. #else /* TCPIPLIB */
  13230. close(fd);
  13231. #endif /* TCPIPLIB */
  13232. }
  13233. }
  13234. return(0);
  13235. }
  13236. /* The following definitions are for Unix */
  13237. #ifndef socket_write
  13238. #define socket_write(f,s,n) write(f,s,n)
  13239. #endif /* socket_write */
  13240. #ifndef socket_read
  13241. #define socket_read(f,s,n) read(f,s,n)
  13242. #endif /* socket_read */
  13243. int
  13244. fwdx_write_data_to_channel(channel, data, len)
  13245. int channel; char * data; int len;
  13246. {
  13247. int sock, count, try=0, length = len, i;
  13248. if ( len <= 0 )
  13249. return(0);
  13250. for ( i=0; i<MAXFWDX ; i++ ) {
  13251. if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel)
  13252. break;
  13253. }
  13254. if ( i == MAXFWDX ) {
  13255. debug(F110,"fwdx_write_data_to_channel",
  13256. "attempting to write to closed channel",0);
  13257. return(-1);
  13258. }
  13259. sock = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].fd;
  13260. debug(F111,"fwdx_write_data_to_channel","socket",sock);
  13261. ckhexdump("fwdx_write_data_to_channel",data,len);
  13262. fwdx_write_data_to_channel_retry:
  13263. if ((count = socket_write(sock,data,len)) < 0) {
  13264. int s_errno = socket_errno; /* maybe a function */
  13265. debug(F101,"fwdx_write_data_to_channel socket_write error","",s_errno);
  13266. #ifdef BETATEST
  13267. printf("fwdx_write_data_to_channel error\r\n");
  13268. #endif /* BETATEST */
  13269. #ifdef OS2
  13270. if (os2socketerror(s_errno) < 0)
  13271. return(-2);
  13272. #endif /* OS2 */
  13273. return(-1); /* Call it an i/o error */
  13274. }
  13275. if (count < len) {
  13276. debug(F111,"fwdx_write_data_to_channel socket_write",data,count);
  13277. if (count > 0) {
  13278. data += count;
  13279. len -= count;
  13280. }
  13281. debug(F111,"fwdx_write_data_to_channel retry",data,len);
  13282. if ( len > 0 )
  13283. goto fwdx_write_data_to_channel_retry;
  13284. }
  13285. debug(F111,"fwdx_write_data_to_channel complete",data,length);
  13286. return(length); /* success - return total length */
  13287. }
  13288. VOID
  13289. fwdx_check_sockets(fd_set *ibits)
  13290. {
  13291. int x, sock, channel, bytes;
  13292. static char buffer[32000];
  13293. debug(F100,"fwdx_check_sockets()","",0);
  13294. if ( sstelnet && !TELOPT_ME(TELOPT_FORWARD_X) ||
  13295. !sstelnet && !TELOPT_U(TELOPT_FORWARD_X)) {
  13296. debug(F110,"fwdx_check_sockets()","TELOPT_FORWARD_X not negotiated",0);
  13297. return;
  13298. }
  13299. for (x = 0; x < MAXFWDX; x++) {
  13300. if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd == -1 ||
  13301. TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend )
  13302. continue;
  13303. sock = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd;
  13304. if (FD_ISSET(sock, ibits))
  13305. {
  13306. channel = TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id;
  13307. debug(F111,"fwdx_check_sockets()","channel set",channel);
  13308. bytes = socket_read(sock, buffer, sizeof(buffer));
  13309. if (bytes > 0)
  13310. fwdx_send_data_from_channel(channel, buffer, bytes);
  13311. else if (bytes == 0) {
  13312. fwdx_close_channel(channel);
  13313. fwdx_send_close(channel);
  13314. }
  13315. }
  13316. }
  13317. }
  13318. int
  13319. fwdx_init_fd_set(fd_set *ibits)
  13320. {
  13321. int x,set=0,cnt=0;
  13322. if ( sstelnet && !TELOPT_ME(TELOPT_FORWARD_X) ||
  13323. !sstelnet && !TELOPT_U(TELOPT_FORWARD_X)) {
  13324. debug(F110,"fwdx_init_fd_set()","TELOPT_FORWARD_X not negotiated",0);
  13325. return(0);
  13326. }
  13327. if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket != -1) {
  13328. set++;
  13329. FD_SET(TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket, ibits);
  13330. }
  13331. for (x = 0; x < MAXFWDX; x++) {
  13332. if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd != -1) {
  13333. cnt++;
  13334. if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend)
  13335. continue;
  13336. set++;
  13337. FD_SET(TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd, ibits);
  13338. }
  13339. }
  13340. if (set + cnt == 0) {
  13341. return(-1);
  13342. } else {
  13343. return(set);
  13344. }
  13345. }
  13346. #ifdef NT
  13347. VOID
  13348. fwdx_thread( VOID * dummy )
  13349. {
  13350. fd_set ifds;
  13351. struct timeval tv;
  13352. extern int priority;
  13353. int n;
  13354. setint();
  13355. SetThreadPrty(priority,isWin95() ? 3 : 11);
  13356. while ( !sstelnet && TELOPT_U(TELOPT_FORWARD_X) ||
  13357. sstelnet && TELOPT_ME(TELOPT_FORWARD_X))
  13358. {
  13359. FD_ZERO(&ifds);
  13360. n = fwdx_init_fd_set(&ifds);
  13361. if (n > 0) {
  13362. tv.tv_sec = 0;
  13363. tv.tv_usec = 2500;
  13364. if ( select(FD_SETSIZE, &ifds, NULL, NULL, &tv) > 0 )
  13365. fwdx_check_sockets(&ifds);
  13366. } else if (n < 0) {
  13367. TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
  13368. ckThreadEnd(NULL);
  13369. } else {
  13370. sleep(1);
  13371. }
  13372. }
  13373. }
  13374. #endif /* NT */
  13375. #endif /* CK_FORWARD_X */
  13376. #endif /* TNCODE */
  13377. #endif /* NETCONN */