ǵdM IDENT.SAV7& IDENT.SAV7BACKUP [IDENT...]*.* [HALL]IDENT.SAV/SAV/LOG/BLOCK=2048 HALL F৓V6.1 _SYBIL:: 6 _DKA100: V6.1  *[IDENT]1-README.FIRST;5+,>./F 4Kt-=0123KPWO56.{ۗ7`pF҃89GFHJ'IDENT Server Documentation, 29-Apr-1994;** COPYRIGHT 1993, 1994 TGV, INC. ALL RIGHTS RESERVED.@** THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR>** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITAIONT, IMPLIEDG** WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.**?** This software is UNSUPPORTED by TGV. Use at your own risk.?** Comments may be forwarded to the author at madison@tgv.com.1. DESCRIPTIONH This directory contains the source and object code, and executables,K for a server that implements the "Identification protocol" described in RFC 1413.< This program REQUIRES MultiNet V3.3 or later to operate.2. INSTALLATION? Executables are provided for both VAX/VMS V5.0 or later andF OpenVMS AXP V1.5 or later. If you wish to rebuild the executables' from sources, you have two options:F - If you have DEC/MMS on your system, use the MMS description@ file provided in this directory. On  ; IDENT.SAV>=[IDENT]1-README.FIRST;5KVAX systems, use $ MMS On AXP systems, use# $ MMS/MACRO=__AXP__=1B - If you do not have MMS installed on your system, use theA MAKE command procedure provided in this directory. For- both VAX and AXP systems, just type $ @MAKEE Once you have built the executable image, copy it to the MULTINET$ common directory on your system:F $ COPY IDENT_SERVER.VAX-EXE MULTINET_COMMON_ROOT:[MULTINET]*.EXE orF $ COPY IDENT_SERVER.AXP-EXE MULTINET_COMMON_ROOT:[MULTINET]*.EXE5 Also copy over the file IDENT_SERVER_STARTUP.COM:E $ COPY IDENT_SERVER_STARTUP.COM MULTINET_COMMON_ROOT:[MULTINET]H and add the following line to your system startup command procedure,. at some point _after_ MultiNet is started:& $ @MULTINET:IDENT_SERVER_STARTUP. This will create the IDENT server process.3. HOW IT WORKS> Please refer to the source code for information on how the@ server works. Please refer to RFC 1413 for more information* on the Identification protocol itself.# IDENT.SAVF=[IDENT]DESCRIP.MMS;7:B*[IDENT]DESCRIP.MMS;7+,F./F 4:&-=0123KPWO56l~o)7F҃89GFHJ ! DESCRIP.MMS!3! MMS description file for building IDENT server.!! Copyright 1993, TGV, Inc.!.IFDEF __AXP__OBJ = .AXP-OBJEXE = .AXP-EXEOPT = .AXP-OPT.ELSEOBJ = .VAX-OBJEXE = .VAX-EXEOPT = .VAX-OPT.ENDIF .SUFFIXES :#.SUFFIXES : $(EXE) $(OBJ) .C $(OPT) .C$(OBJ) : $(CC)$(CFLAGS) $(MMS$SOURCE)%CFLAGS = /NOLIST/OBJECT=$(MMS$TARGET)-LINKFLAGS = /NOTRACE/NOMAP/EXEC=$(MMS$TARGET):IDENT_SERVER$(EXE) : IDENT_SERVER$(OBJ),IDENT_SERVER$(OPT)1 $(LINK)$(LINKFLAGS) IDENT_SERVER$(OPT)/OPTION*[IDENT]IDENT_SERVER.AXP-EXE;7+,i./F 4-=0123KPWO56Bיhۗ7࿻F҃89GFHJO  IDENT.SAVi=[IDENT]IDENT_SERVER.AXP-EXE;7h0h(8g[0p98gۗ IDENT_SERVERV1.0A10-62$ $ $ $ $J$( DN MULTINET_SOCKET_LIBRARY_0018.  DECC$SHR_0014 LIBRTL_0014" LIBOTS_001@^6SYS$PUBLIC_VECTORS_0010   0@p (H0(`| P00 0X  00@ 7n IDENT.SAVi=[IDENT]IDENT_SERVER.AXP-EXE;7`00 00`0 @0x`  ERROR%d,%d:%s:%s ' USERID:VMS0(P 0 PERNE| 00P`ERNE INVALID-PORTHIDDEN-USERNO-USER0` 0ERNE 00ERNE @0P ERNE 0x0ERNE 0 ERNE `0@ MULTINET_TCB_SEARCH_FINISHMULTINET_TCB_SEARCHMULTINET_TCB_SEARCH_INITMULTINET_VMS_SHAREABLE_INET: 8  L0 00:01:00.00s IDENT.SAVi=[IDENT]IDENT_SERVER.AXP-EXE;7'#~(^0^8~@HP޴XGG#xb#Z@0D HbG GXBG`bGG@Zk0D HBH"Pb4G@ZkTG >4G>G vH(BTG1vH G0bG(GGZk0D ,HG0D@&c"0"(BG3v`JG1v`J 0bG(r_"GGGGZk0D ,H0Do@B"GGBZk4Gݢ4GhB6JpbPBݲUpZkqSH="0bTG(BG!HGFC=GcG3v`JG1v`J (GZk0D ,Hj0D?@cG~GTG#v`H(BG1v`H G0bG(GeZk0D`,HT0D%8B("@b="TG@Zk0D`, G _8BG@bGTGt@ZkG0 D$=0`@C"_(b#9@GDGGG(]0]8}@HPݤX`#k/=4G 4G]r G[@Zk$=/xBGb@@ZkG .P JFL .P JFf .P JF ,E HD#G~_"^G^GGG# @B( `"!v H Hb1v H(C@Zk0D G8b4G0BrZkG]] #k#~^^ ~(0GG#`/,!/HMG0 DB (G b#@8b="XbTGPB(c GZk0D pBGxb4GrZk"pBGxbG "G~Zk0D`Gxb4GpBrZk}GTGBG G8c ~G~ vH b/vI1vH/vI (Zk0D`pBGxb4GrZkG]] }(0@#k IDENT.SAVi=[IDENT]IDENT_SERVER.AXP-EXE;7 ,@ HD#G~^G1,1H G(0 D {P{#3DP@G] #kG,@ HD#G~r_"^G^G ~G(G#G( GGB0vJb1vJ"G (F~Zk#"(bTG B"{~Zk L"b#GK@G] }](0#k#~0^8^@~HPGGGL"*#">C"b#@0D D G_&(0R" B"1v J(0<4vJ<Gpb#@ <"(#"G4Gb#@0D "=,A0H'H 0B"GGG@B"4GGb#@G0]8]@}HP`#kG#~^^~ G#GGB"b4GqZk B#"0BG(bGGGcZk0D BGb4GqZk@GBGbG$ C0vJ^4G1vJG 8( ZkG]}] 0#kG#~^^~ GGG#,#Hd`0 D G b#I@N#,"0H^ G b#@@EG#.!"PJJXF A"a.Gb#SrJr>P_3G.#"JI /Cr."StJgJaF` ".UJJXF%01BR"G4G01BR".#"GJ. @"PB@.J+GG`b#7B`_G]]} 0#kGR/Gb#ZRKR?_G,@ HD,@ HD?G b#@1,A 1H0D1,A 1H0D.T JFð#~^^ ~(08޴@GG],GC""@HHDGCBP."RPJGJAF@#,c 1˪ IDENT.SAVi=[IDENT]IDENT_SERVER.AXP-EXE;7  A H'H GC?DBP."RPJGJAF_#, A H'H G/ GC?D@Br.R"SrJgJaF%`%D# GC_C.c"RSJGJ_F@a.! SaJgJ`F`c "c.B2FBA!@StJ2@gJ `F@4,"A4H'H!D eF$ B@BGb0vJ4GrmZkG.qHc"PJF>C.RSJGJ@EFG_FCB.R"WJJF /c ##XKKGBX/#ZXKGKAG_c/# [aKgK`eG`. &"PJGJCF0Bp."SpJgJaF`G. "TJJF4BT."RTJGJAF_.&#WJJ^G&F7B."VJJFF/& ZAKGK_G;B{,{#C{HgH`DH` "f.C:FCPBSuJBgJ`F3B.s"TJJFC4B0vK}4GblZk?`G#,pHF"bA#H0D#<&.Q2J'J 4GG?FCB.1"UJJF . "VJJFB/"XKKG&/ Y&K'K 4GGG]] }(08ݤ@P#k/. HP JF>B#, HA #H0D#<À#4G~G(^0^8~@HP޴X`h>p^xGGG¤G =G}.]"G`2J0"SrJ"`Fr>.v4HG(B 8bUJ F>[G@Zk @8D0F 4GBboZk(! ]GGGG["G@ZkGy/(},)= CaHgH`$.Q$J$>FGhGBG3wZk`H= } "G@BGv HHbX)! D=G!GGKZk G0@E 4GGG QKJ IDENT.SAVi=[IDENT]IDENT_SERVER.AXP-EXE;7[@ZkGL = $.Q$J$>FG?=%1@eHPBXb "v H"%D=GGGGGwLZkG 0D@&G4GG[@ZkG(}#fHfH` ]*FIFI @),A)H'H?DA.! PJJF*1@A*FIFI]_]2FJFJ@.TJ>ƠG[G4G@Zk4GG(]0]8}@HPݤX`h=p]x#k#4G~^^ ~(08޴@HPG#GG(GG(BRJ0b@  0vJDlZk<$G0b4G(BR H0v H/%.z["N ݔ|RrN3mk8kt|xgDuHIq ,/[\D?Tu CBszɧ_B} 8iS5뗽U[P+D23XcX)Xt6K,w}Y>*MϥL ^6-i1o(XE?5lĆ&<;˙Dc 1qT^Z Z5K ΑrČ'k7sEވzulUٗ;.|b{JsK#jM8ED.H5ٺځg` D6h C' ҍ5èҜ” Sy/^Ś/gi9YqʢHKHsq;,$߲Rg^? _;s 42Z *=j\l+ < p/;0SCƃ*ϲ3؋c7X3ײŞDa $HiDٳ7rM;b 1ɩUvbK w"G1RZC ,ј )N.G(n#9kG &fbD?dA'fJJOSrl hF+(„jg#j#R ;<qb$s5z R:ok[a%Us MosEY8KtU&7zUg $fQ($gߕ%f&GwثfYM]0ksU~Jy rPKI+_eweYIej6yRƂ"GiQA&D2u.LN )榇@H?Ѥqaf|̹ReŬnDﺰxpG1^I4.OYZe-탅wŠ4:_susRqI|}i .S׫ۥBMw@O@M PORy3}6%s{0CFKE4( xcsPP<$g ) IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6's*[IDENT]IDENT_SERVER.AXP-OBJ;6+,j.'/F 4'&-=0123KPWO'56:bۗ7F҃89GFHJHH IDENT_SERVERV1.029-APR-1994 16:08DEC C V1.2-001 P $READONLY$ $BSS$`$DATA$$LINK$p $LITERAL$i$$CODE$ $ABS$DECC$GA___CTYPEDECC$GA_STDERR DECC$GA_STDINDECC$GA_STDOUT DECC$GSPRINTF DECC$STRLEN SYS$ASSIGN SYS$BINTIM SYS$CANCEL SYS$CANTIM SYS$DASSGN SYS$DCLEXH SYS$HIBERSYS$QIOSYS$QIOW SYS$SETIMRSYS$WAKE LIB$FIND_IMAGE_SYMBOL LIB$FREE_VM LIB$GETDVI LIB$GETJPI LIB$GET_VMLIB$SIG_TO_RETLIB$STOP0JX EXIT_HANDLER(JMAIN0JDO_ACCEPT_WAIT0JACCEP 承h IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6']T_WAIT_AST0J ACCEPT_AST(J`xPROCESS0JP PROCESS_20JP`GET_LINE0J`  GET_LINE_20J  PARSE_LINE0J P LOCATE_USER0Jx SEND_REPLY8JPLOCATE_SEARCH_SYMBOLS0J CLOSE_DOWN0JSCHEDULE MULTINET_KERNEL_NLISTKLSEEKKLREADMULTINET_HTONSMULTINET_NTOHS DECC$$SHELL_HANDLER(Jp__MAIN DECC$EXIT DECC$MAINOTS$MOVEOTS$FILL = 6 6 =6 = 6 =6 = 6 = 6 = m m= 4=_INET:=  8444 4 4= L8=0 00:01:00.00H= 4= 4=b b =0;=  DK1 IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'J;;LIB$STOPSYS$QIO=0@;=p 7DECC$$SHELL_HANDLER= LIB$FIND_IMAGE_SYMBOL=( 7LIB$SIG_TO_RET ;8;X;;=0(;=`| ;SYS$QIOW LIB$GET_VM SYS$DCLEXH SYS$ASSIGN=MULTINET_HTONS SYS$HIBER8OTS$MOVE8OTS$FILL=0;=0  DECC$EXIT DECC$MAIN=0X;=   SYS$CANCEL=0;=@ SYS$WAKE=0;=0  LIB$FREE_VM! SYS$DASSGN=0`;=0 # SYS$SETIMR@;;;=0x;=` %MULTINET_NTOHS=ERROR=%d,%d:%s:%s ' DECC$STRLEN) DECC$GSPRINTF= USERID:VMS =0(P;= 7DECC$GA___CTYPE7KLSEEK7 MULTINET_KERNEL_KX IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'. _NLIST7KLREAD+ LIB$GETDVI- LIB$GETJPI=0 ;= PERNE| 00P;=&`ERNE INVALID-PORT= HIDDEN-USER= NO-USER=0` ;= 0ERNE 0;=0ERNE / SYS$CANTIM=0P;=  ERNE 0x;=0ERNE 1 SYS$BINTIM=0;= ERNE ;`;=0;=@ ;; =$MULTINET_TCB_SEARCH_FINISH =MULTINET_TCB_SEARCH8="MULTINET_TCB_SEARCH_INITX= MULTINET_VMS_SHAREABLE =,$#~(^0^8~@HP޴XGG#xb#Z@0D HbG GXBG`bGG@Zk0D HBH"Pb4G@ZkTG >4G>G vH(BTG1vH G0bG(GG@Zk0D ,HG0D@&c"0"(BG3v`JG1v`J 0bG(r_"GGGG@Zk0D ,H0Do@B"GG@Zk4Gݢ4GhB6JpbPBݲ@ZkqSH="0bTG(BG!HGFC=GcG3v`JGrjw IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'+ 1v`J (G@Zk0D ,Hj0D?@cG~GTG#v`H(BG1v`H G0bG(G@Zk0D`,HT0D%8B("@b="TG@Zk0D`, G _8BG@bGTG@ZkG0 D$=0`@C"_(b#9@GDGGG(]0]8}@HPݤX`#k/=4G 4G]r G[@Zk$=/xBGb@ZkG .P JFL .P JFf .P JF ,E HD#G~_"^G^GGG# @B( `"!v H Hb1v H(@Zk0D G8b4G0B@ZkG]] #k#~^^ ~(0GG#`/,!/HMG0 DB (G b#@8b="XbTGPB(c G@Zk0D pBGxb4G@Zk"pBGxbG "G@Zk0D`Gxb4GpB@Zk}GTGBG G8c ~G~ vH b/vI1vH/vI (@Zk0D`pBGxb4G@ZkG]] }(0@#k,@ HD#G~^G1,1H G(0 D {P{#3DP@G] #kG,@ HD#G~r_"^G^G ~G(G#G( GGB0vJb1vJ"G (@Zk#"(bTG B"@Zk L"b#GK@G] }](0#k#~0^8^@~HPGGGL"*#">C"b#@0D D G_&(0R" B"1v J(0<4vJ<Gpb#@ <"(#"G4Gb#@0D "w IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'n=,A0H'H 0B"GGG@B"4GGb#@G0]8]@}HP`#kG#~^^~ G#GGB"b4G@Zk B#"0BG(bGGG@Zk0D BGb4G@Zk@GBGbG$ C0vJ^4G1vJG 8(@ZkG]}] 0#kG#~^^~ GGG#,#Hd`0 D G b#I@N#,"0H^ G b#@@EG#.!"PJJXF A"a.Gb#SrJr>P_3G.#"JI /Cr."StJgJaF` ".UJJXF%01BR"G4G01BR".#"GJ. @"PB@.J+GG`b#7B`_G]]} 0#kGR/Gb#ZRKR?_G,@ HD,@ HD?G b#@1,A 1H0D1,A 1H0D.T JFð#~^^ ~(08޴@GG],GC""@HHDGCBP."RPJGJAF@#,c  A H'H GC?DBP."RPJGJAF_#, A H'H G/ GC?D@Br.R"SrJgJaF%`%D# GC_C.c"RSJGJ_F@a.! SaJgJ`F`c "c.B2FBA!@StJ2@gJ `F@4,"A4H'H!D eF$ B@BGb0vJ4G@ZkG.qHc"PJF>C.RSJGJ@EFG_FCB.R"WJJF /c ##XKKGBX/#ZXKGKAG_c/# [aKgK`eG`. &"PJ8L IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'GJCF0Bp."SpJgJaF`G. "TJJF4BT."RTJGJAF_.&#WJJ^G&F7B."VJJFF/& ZAKGK_G;B{,{#C{HgH`DH` "f.C:FCPBSuJBgJ`F3B.s"TJJFC4B0vK}4Gb@Zk?`G#,pHF"bA#H0D#<&.Q2J'J 4GG?FCB.1"UJJF . "VJJFB/"XKKG&/ Y&K'K 4GGG]] }(08ݤ@P#k/. HP JF>B#, HA #H0D#<À#4G~G(^0^8~@HP޴X`h>p^xGGG¤G =G}.]"G`2J0"SrJ"`Fr>.v4HG(B 8bUJ F>[G@Zk @8D0F 4GBb@Zk(! ]GGGG["G@ZkGy/(},)= CaHgH`$.Q$J$>FGhGBG@Zk`H= } "G@BGv HHbX)! D=G!GG@Zk G0@E 4GGG[@ZkGL = $.Q$J$>FG?=%1@eHPBXb "v H"%D=GGGGG@ZkG 0D@&G4GG[@ZkG(}#fHfH` ]*FIFI @),A)H'H?DA.! PJJF*1@A*FIFI]_]2FJFJ@.TJ>ƠG[G4G@Zk4GG(]0]8}@HPݤX`h=p]x#k#4G~^^ ~(08޴@HPG#GG(GG(BRJ0b@  0vJ@Zk<$G0b4G(BR H0v H@ZkDV IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'8" pbx"hBpDGGGGGGG@ZkGG GXB(vI1vI@ZkGGGhBGG pb(@Zk dL İGb#_G] }](08ݤ@HP`#k#4G~G^TG^~ GGG BG(b@ZkG$b#@G]}] 0#k#~^G4G [{0vJ0vJ@ZkG] #kG#~@^H^P~X``GGPX"x8@0=H"(p" =<hB4=,]$`TG`q3 J]@JQF]`8} 0="0BG8btG G@Zk0D D"8b(="0BGtG@Zk0D 0BD"8b ="GtG@Zk`G@]H]P}X`p#k#C~G^2_"^G G# GGG!v HBG1v H b(@Zk4G8b0B vH0vH@Zk(b="TG B("@ZkG]] 0#kG#~^ ^(~0GG b=  c 00F G×=4G@ "0B="8bTG@Zk = = = BTG(bGG@ZkG ](}]0@#kG#p4G~^G [({ vH0vH@ZkG4G] #kG#4G~^ ^(G#G 0B =  >8b@Zkhb#_(bG4G B@ZkG ]](0#k4 PGh SYS$ASSIGN4Xb# SYS$ASSIGN4 d@h SYS$ASSIGN4 pG SYS$DCLEXH4 a  IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'Yxb# SYS$DCLEXH4 @ SYS$DCLEXH4GSYS$QIOW4b#SYS$QIOW4@SYS$QIOW4 GTSYS$QIOW40b#SYS$QIOW4P@TSYS$QIOW4pGOTS$FILL4@OTS$FILL4GMULTINET_HTONS4b#MULTINET_HTONS4@MULTINET_HTONS4b#SYS$QIOW4GSYS$QIOW4@SYS$QIOW4PG|SYS$QIOW4hb#SYS$QIOW4x@|SYS$QIOW4 G LIB$GET_VM4 b# LIB$GET_VM4 @ LIB$GET_VM4 G LIB$GET_VM4 b# LIB$GET_VM4 @ LIB$GET_VM4G SYS$HIBER4b# SYS$HIBER4@ SYS$HIBER,$G\SYS$QIO ,Lb#SYS$Q+g IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'ĈIO,X@\SYS$QIO4hb#LIB$STOP4pGxLIB$STOP4t@xLIB$STOP4 b# LIB$GET_VM4 G LIB$GET_VM4 @ LIB$GET_VM4G$LIB$STOP4b#LIB$STOP4 @$LIB$STOP4 ,GH SYS$ASSIGN44b# SYS$ASSIGN4 D@H SYS$ASSIGN4Tb#LIB$STOP4\GdLIB$STOP4`@dLIB$STOP,tGSYS$QIO,b#SYS$QIO,@SYS$QIO4GLIB$STOP4b#LIB$STOP4@LIB$STOP4GSYS$QIOW4b#`SYS$QIOW4@SYS$QIOW42b#` SYS$BINTIM41G SYS$BINTIM41@ SYS$BINTIM4GLIB$STOP4b#PLIB$STOP41-t +-N  {_N'bflov csmd8 uv$lhھE#˨ttt-a&r)EKJSև -Ao wWj6ܩCq(4#IW}ςܭC',z"_= B7QI=OP$6AO v}t܈oajR?<_'_+SV 7<3=o,Ž >E4et f=_tJk vT3Zi3>n6TBx3GTDV)[pi.şH5Pw?@ѫd'7#O@ibT&L )tg.]HD'S'QJ.:zаg*Wb~A" pNԻ:b kOGM[o^0^tm&1CFteB.Ep;4Ij6WX4;;^9F`}H=~{:<([m !,_k`4&*4Wrl8yQ4Q꾗޹ z2L-=BtB>ɦW5&@T!o1ǟ$KgDpI!9Fjqw$Hl7ۀ|N4/,3f< VM[f ElA77Uek,&*q x-ɷ jq׮HE:ɏݯEi=ZƼRiѥ]>BZH};Q }0`]mc zP=}*\(7拧CAV؍SF!OgV'gcP:S0Z2ɡ%pD|4LpBMie4 7XECoL vA&UL:8=iAFxR<+TnB,b"W 4κw,(jG TdNEMqq'l-x=}4.|9:;4^輗YH)KB#$eJ)-v*cFy:E#Fq-ѵUXE}tbqP_&otRGfA=Sc8%RK dC=D!t=`'4GHǰ RD"5!1}K>d* ~BAO0E a wU^'RP_ wS؄2W/PF'}EW:6 ȡs.Lu-TA@Q̼ oTkK- \-9 2'nEAJ hsDر KvhE\C:JH7vLVd\U+dj)f/wVY+N j IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'@LIB$STOP4#G SYS$SETIMR4$b#P SYS$SETIMR4#@ SYS$SETIMR4GLIB$STOP4b#PLIB$STOP4@LIB$STOP,G@ SYS$QIO,b#PSYS$QIO,< @@ SYS$QIO4 G8 MULTINET_HTONS4( b#MULTINET_HTONS44 @8 MULTINET_HTONS4 G8MULTINET_HTONS40b#MULTINET_HTONS44@8MULTINET_HTONS4G$LIB$STOP4b# LIB$STOP4 @$LIB$STOP4'G DECC$STRLEN4'@ DECC$STRLEN4+G LIB$GETDVI4,b#  LIB$GETDVI4+@ LIB$GETDVI4-<Gt LIB$GETJPI4.@b#  LIB$GETJPI4-p@t LIB$GETJPI4%GMULTINET_NTOHS4&b#MULTINET_NTOHS4%@MULTINET_NTOHS4&f0 IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'{!b#MULTINET_NTOHS4%GMULTINET_NTOHS4%@MULTINET_NTOHS4*b# DECC$GSPRINTF4) G4 DECC$GSPRINTF4)0@4 DECC$GSPRINTF4'HGX DECC$STRLEN4'T@X DECC$STRLEN4pGSYS$QIOW4b#SYS$QIOW4@SYS$QIOW4/G$ SYS$CANTIM40b# SYS$CANTIM4/ @$ SYS$CANTIM4tG SYS$CANCEL4x{#@ SYS$CANCEL4@ SYS$CANCEL<@G\LIB$FIND_IMAGE_SYMBOL<Hb#PLIB$FIND_IMAGE_SYMBOL<X@\LIB$FIND_IMAGE_SYMBOL<hb#PLIB$FIND_IMAGE_SYMBOL<pGLIB$FIND_IMAGE_SYMBOL<|@LIB$FIND_IMAGE_SYMBOL<GLIB$FIND_IMAGE_SYMBOL<b#PLIB$FIND_IMAGE_SYMBOL<@LIB$FIND_IMAGE_SYMBOL4G8SYS$QIOW4,b#SYS$QIOW44U IDENT.SAVj=[IDENT]IDENT_SERVER.AXP-OBJ;6'Q$@8SYS$QIOW4"@b# SYS$DASSGN4!DGX SYS$DASSGN4!T@X SYS$DASSGN4 Xb# LIB$FREE_VM4hGt LIB$FREE_VM4p@t LIB$FREE_VM4 G LIB$GET_VM4 b# LIB$GET_VM4 @ LIB$GET_VM4 G8SYS$WAKE4(b#SYS$WAKE44@8SYS$WAKE4xG SYS$CANCEL4|{# SYS$CANCEL4@ SYS$CANCEL4G DECC$MAIN4b#p DECC$MAIN4@ DECC$MAIN4b#p DECC$EXIT4G  DECC$EXIT4@  DECC$EXIT p& IDENT.SAVk=[IDENT]IDENT_SERVER.AXP-OPT;2ڱ*[IDENT]IDENT_SERVER.AXP-OPT;2+,k./F 46-=0123KPWO56Ro)7`F҃89GFHJIDENT_SERVER.AXP-OBJMULTINET_SOCKET_LIBRARY/SHARE*[IDENT]IDENT_SERVER.C;56+,l.?/F 4l?=-=0123KPWO>56]ۗ7F҃89GFHJ/***++** FACILITY: IDENT server**6** ABSTRACT: RFC 1413 Identification protocol server.**** MODULE DESCRIPTION:**C** Implementation of the RFC 1413 (wretched awful) Identification-** protocol, as a standalone server process.**** AUTHOR: M. MadisonE** COPYRIGHT 1993, 1994 TGV, INC. ALL RIGHTS RESERVED.**@** THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR>** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, IMPLIEDG** WARRANTIES OF ME'7 IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?|RCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.**?** This software is UNSUPPORTED by TGV. Use at your own risk.?** Comments may be forwarded to the author at madison@tgv.com.**** CREATION DATE: 27-MAY-1993**** MODIFICATION HISTORY:**1** 27-MAY-1993 V1.0 Madison Initial coding.8** 10-AUG-1993 V1.1 Madison Moved to CONTRIB area.K** 15-SEP-1993 V1.2 Madison Moved internals stuff into vms_shareable.A** 10-NOV-1993 V1.3 Madison Converted to standalone server.9** 22-NOV-1993 V1.3-1 Madison Comments, code cleanup.E** 29-APR-1994 V1.3-2 Madison Cancel timer in I/O completion AST.**--*/#include #include #include #ifdef __GNUC__#include #include #include #include #include #include #include @ extern unsigned int lib$sig_to_ret(), lib$ast_in_prog(void);#else#include #include #include #include #include #include #include #include #ifdef __DECC#include #else#pragma builtins#endif#endif6#include "multinet_root:[multinet.include.sys]types.h"7#include "multinet_root:[multinet.include.sys]socket.h"7#include "multinet_root:[multinet.include.netinet]in.h":#include "multinet_root:[multinet.include.vms]inetiodef.h"/*=** Under VAX C and DEC C on both VAX and ]  IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?MpAXP systems, we use=** the built-in queue instructions. Under GNU C, we use our:** own routines for inserting and removing queue entries.*/#ifdef __ALPHAL#define queue_insert(item,pred) __PAL_INSQUEL((void *)(pred),(void *)(item))M#define queue_remove(entry,addr) (((struct QUE *)entry)->head == entry ? 0 :\E (__PAL_REMQUEL((void *)(entry),(void *)(addr)),1))#else#ifdef __GNUC__ static void queue_insert(); static int queue_remove();#else2#define queue_insert(item,pred) _INSQUE(item,pred)M#define queue_remove(entry,addr) (((struct QUE *)entry)->head == entry ? 0 :\+ (_REMQUE(entry,addr),1))#endif#endif/*** Handy status-checking macro*/$#define OK(x) $VMS_STATUS_SUCCESS(x)/*-** Structure for tracking client connections*/ struct CLIENT {A unsigned short iosb[4]; /* I/O status block */D unsigned int timeout[2]; /* connection timeout value */D int io_completed, got_cr, size; /* input buffer tracking */8 char *bufp; /* variables */= unsigned short chan; /* network channel */B void (*completion_routine)(); /* for I/O completion */D struct sockaddr_in lclsin; /* local side of connection */8 struct { /* remote side */A unsigned int sinlen; /* of connection */E struct sockaddr_in remsin; /* with leading length */7 } r; + IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l? /* for accept call */; char buf[1024]; /* input buffer */ };/*(** Structure for managing work requests*/ struct WRK {> struct WRK *flink, *blink; /* queue header */> void (*routine)(); /* routine to be called */; void *arg; /* argument for routine */ };/*** Generic queue structure*/ struct QUE { void *head, *tail; };/*** OWN storage*/G static int (*search_init)(); /* search routines */E static int (*search)(); /* from MultiNet_- */F static int (*search_finish)(); /* VMS_Shareable */M static $DESCRIPTOR(inet_device, "_INET:"); /* INET device name */N static $DESCRIPTOR(timerdsc, "0 00:01:00.00"); /* connection timeout */N static int cl_size = sizeof(struct CLIENT); /* for get_vm/free_vm */L static int wrk_size = sizeof(struct WRK); /* for get_vm/free_vm */J static unsigned short listen_chan; /* Listener channel */I static unsigned short aw_iosb[4]; /* Accept-wait IOSB */E static int one = 1; /* for setsockopt call *//*** Exit handler stuff*/% static unsigned int final_status; unsigned int exit_handler(); static struct { void *flink; unsigned int (*exh)(); unsigned int argcnt; unsigned int *statusp;3 } exhblk = {Q: IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?t 0, exit_handler, 1, &final_status};/*E** These queues track the work requests to be processed and the free** work-request cells.*/2 static struct QUE wrkque = {&wrkque, &wrkque};6 static struct QUE freeque = {&freeque, &freeque}; /*** Forward declarations*/ unsigned int main(void); void Do_Accept_Wait(void); void Accept_Wait_AST(void);% void Accept_AST(struct CLIENT *);" void Process(struct CLIENT *);$ void Process_2(struct CLIENT *);# void Get_Line(struct CLIENT *);% void Get_Line_2(struct CLIENT *);H unsigned int Parse_Line(char *, unsigned short *, unsigned short *);H unsigned int Locate_User(struct sockaddr_in *, struct sockaddr_in *,! char *, int);2 void Send_Reply(int, struct CLIENT *, char *);3 static void IO_Completion_AST(struct CLIENT *);0 static void IO_Timeout_AST(struct CLIENT *);- unsigned int Locate_Search_Symbols(void);% void Close_Down(struct CLIENT *); void Schedule();/*** External references*/' extern int multinet_kernel_nlist(); extern int klseek(); extern int klread();G extern unsigned short htons(unsigned short), ntohs(unsigned short); /***++** ROUTINE: main**** FUNCTIONAL DESCRIPTION:**<** Server main routine. Locates the routines we need fromG** MULTINET_VMS_SHAREABLE. Sets up listener channel and queue of freeE** work requests, fires up initial network accept. Then goes into a"** loop processing workW# IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l? requests.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**** main(void)**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: Several.**** SIDE EFFECTS: Several.****--*/unsigned int main(void) { struct sockaddr_in lclsin; struct CLIENT *cl; struct WRK *wrk; unsigned short iosb[4]; unsigned int status; int i;/*=** Make sure the support is there in MultiNet for this stuff*/% status = Locate_Search_Symbols();# if (!OK(status)) return status;/*** Get the listener channel.*/: status = sys$assign(&inet_device, &listen_chan, 0, 0);# if (!OK(status)) return status;/*** Set up the exit handler.*/ sys$dclexh(&exhblk);/*** Create the listener socket.*/= status = sys$qiow(0, listen_chan, IO$_SOCKET, iosb, 0, 0,, AF_INET, SOCK_STREAM, 0, 0, 0, 0);% if (OK(status)) status = iosb[0];# if (!OK(status)) return status;/*** Set the REUSEADDR option*/A status = sys$qiow(0, listen_chan, IO$_SETSOCKOPT, iosb, 0, 0,= SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one), 0, 0);% if (OK(status)) status = iosb[0];# if (!OK(status)) return status;/*** Bind the socket.*/' memset(&lclsin, 0, sizeof(lclsin)); lclsin.sin_family = AF_INET;( lclsin.sin_addr.s_addr = INADDR_ANY;! lclsin.sin_port = htons(113);; status = sys$qiow(0, listen_chan, IO$_BIND, iosb p{ IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?, 0, 0,/ &lclsin, sizeof(lclsin), 0, 0, 0, 0);% if (OK(status)) status = iosb[0];# if (!OK(status)) return status;/*** Fire up the listener.*/= status = sys$qiow(0, listen_chan, IO$_LISTEN, iosb, 0, 0, 16, 0, 0, 0, 0, 0);% if (OK(status)) status = iosb[0];# if (!OK(status)) return status;/**** Set up our initial network I/O context*/' status = lib$get_vm(&cl_size, &cl);# if (!OK(status)) return status;/*%** Build up a queue of work requests*/ for (i = 0; i < 32; i++) {* status = lib$get_vm(&wrk_size, &wrk);$ if (!OK(status)) return status;% queue_insert(wrk, freeque.tail); }/*** Start the ball rolling.*/ Do_Accept_Wait();/*=** Now just sit around waiting for work requests to process.*/ while (1) {. while (queue_remove(wrkque.head, &wrk)) {" (wrk->routine)(wrk->arg);) queue_insert(wrk, freeque.tail); } sys$hiber(); } return SS$_NORMAL; } /* main */ /***++** ROUTINE: Do_Accept**** FUNCTIONAL DESCRIPTION:**2** Starts an accept-wait on the listener socket.**** RETURNS: void**** PROTOTYPE:**** Do_Accept(void)**** IMPLICIT INPUTS: Several.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/void Do_Accept_Wait(void) { unsigned int status;R status = sys$qio(0, listen_chan, IO$_ACCEPT_WAIT, aw_iosb, Accep!Ab$DPP1%oHb^L9W0| s2Q[SE?Sp. ouo30<M3kC/O3f3A 'MH{f  XL2jRs} CDEr(jxM#]+ `5V_;t,W]XPZ{JM3g@ED#EZW! bT:5MM+g|jm# ?EPDbd^xm/g 9<@7 kaj}m? 7Y9&%=Pp8#L il^R ;TDv,K__Se^+niI`Z=ba&F25~F1p`h/j3"*!a'7 6HLYG_jY9i\.%%.U,*Fhcvne9>uolLRB] W]#}9ap~Ap*3+r8Jv l$7 AHQR06iFsH-_iS5usCPnb;g, |iXITY>1U= UJd)F3g8uUp :n&m8:Y `~}0: ps g5ALnq.^nQRj%qS/0.x?Ec1+=c_3sftUb hyciv5^mysppRd1MNYU 2g yk\;}5bE^ED [?j^CN~#$;r Z5' 1th3[tx08dP)A( 1;\7S>cBxQ{D;!ZB _MVXfZ0eS pJX [ M&s5Qzh%DA!oDE4v "L'1s;90PxaTtsH8yZ\ 7uIL{osg1V^%|.[}&F\{$<Rf~~V~(?qST[x+'u/(U5K8$S0Ust*{U #zXBq wjhGxv2uJojAYv!$?9n [ ?p]cIGWc?mOWfIaw mbi??VbioamV"t(*.bV ROEY[GR5]8*=~BK 9+kP] '7DS}$Yt nxz>o-`Wjn)| \1EJ./f}*l$DC2oIJ4TzfUdm16JV\hqKMd*/'G)YFvz3e+{3ySN)r7jg46+e+A"$yK= O62B]<7E{V_|,AuyGca~$9aw!2OT!Mm-e3!Re_U2<:,/)&J3k 2}m(rkBS9Pu[D?&-,TL7|sZ]oNl0; !/zz~XDO?1s~{ccim/tKX O_E}(NBmJ+h&~lOw#4~wbVh*:5ARRANTIES OF ME"dv IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?t_Wait_AST, 0, 0, 0, 0, 0, 0, 0);& if (!OK(status)) lib$stop(status);} /* Do_Accept_Wait */ /***++** ROUTINE: Accept_Wait_AST**** FUNCTIONAL DESCRIPTION:**-** Starts an accept on the listener socket.**** RETURNS: void**** PROTOTYPE:**** Do_Accept(void)**** IMPLICIT INPUTS: Several.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/void Accept_Wait_AST(void) { struct CLIENT *cl; unsigned int status;/*"** If accept-wait failed for some** reason, just ignore.*/ if (!OK(aw_iosb[0])) return;/* ** Schedule another accept-wait*/ Schedule(Do_Accept_Wait, 0);/*"** Set up our network I/O context*/' status = lib$get_vm(&cl_size, &cl);& if (!OK(status)) lib$stop(status);/*** Get a network channel.*/7 status = sys$assign(&inet_device, &cl->chan, 0, 0);& if (!OK(status)) lib$stop(status);/*** Start the accept.*/G status = sys$qio(0, cl->chan, IO$_ACCEPT, cl->iosb, Accept_AST, cl,7 &cl->r, sizeof(cl->r), listen_chan, 0, 0, 0);& if (!OK(status)) lib$stop(status);} /* Accept_Wait_AST */ /***++** ROUTINE: Accept_AST**** FUNCTIONAL DESCRIPTION:**?** AST completion routine for accept call. If the accept wasC** successful, a work request is queued for starting processing on7** the new connection. A new accept is also fired up.**** RETURNS: void**** PROT#H IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?+OTYPE:**9** Accept_AST(struct CLIENT *cl) // invoked as an AST**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/$void Accept_AST(struct CLIENT *cl) {9 Schedule(OK(cl->iosb[0]) ? Process : Close_Down, cl);} /* Accept_AST */ /***++** ROUTINE: Process**** FUNCTIONAL DESCRIPTION:**=** First stage of request processing. The sockaddr for theN** local end of the socket is read (the remote end is filled in automaticallyG** by the accept) and Get_Line is used to wait for the request to come** in from the remote side.**** RETURNS: void**** PROTOTYPE:**$** void Process(struct CLIENT *cl)**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.** ** SIDE EFFECTS: None.****--*/!void Process(struct CLIENT *cl) { int n; unsigned int status;/*$** Get our local socket information*/ n = sizeof(cl->lclsin);: sys$qiow(0, cl->chan, IO$_GETSOCKNAME, cl->iosb, 0, 0,5 &cl->lclsin, &n, 0, 0, 0, 0);/*$** Initialize the I/O timeout value*/' sys$bintim(&timerdsc, cl->timeout);/*** Get the request*/ cl->bufp = cl->buf;! cl->size = sizeof(cl->buf)-1; cl->got_cr = 0; Get_Line(cl);} /* Process */ /***++** ROUTINE: Process_2**** FUNCTIONAL DESCRIPTION:**<** Second stage of p$n2 IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?rocessing. We have now read the identC** request. We parse it; if it is valid, we look up the specified$** sockets and send back the reply.**** RETURNS: void**** PROTOTYPE:**!** Process_2(struct CLIENT *cl)**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/#void Process_2(struct CLIENT *cl) { unsigned int status; char user[33];/*** Parse the request*/O status = Parse_Line(cl->buf, &cl->lclsin.sin_port, &cl->r.remsin.sin_port);/*@** If it didn't parse, but it's just a syntax problem, treat as4** an invalid port specification. Otherwise, punt.*/ if (!OK(status)) {" if (status == SS$_BADPARAM) {! cl->lclsin.sin_port = 0;# cl->r.remsin.sin_port = 0;+ Send_Reply(1, cl, "INVALID-PORT"); } else { Close_Down(cl); } return;/*0** If it parsed OK, try and satisfy the request*/ } else {J status = Locate_User(&cl->r.remsin, &cl->lclsin, user, sizeof(user)); if (OK(status)) { if (user[0] == '\0') {+ Send_Reply(1, cl, "HIDDEN-USER"); return; } else {" Send_Reply(0, cl, user); return; } } else {& Send_Reply(1, cl, "NO-USER"); return; } }} /* Process_2 */ /***++** ROUTINE: Get_Line**** FUNCTIONAL DESCRIPTION:**A** Reads a line of text from the c% IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?`lient, which should terminate** in a CR/LF sequence.**** RETURNS: void**** PROTOTYPE:** ** Get_Line(struct CLIENT *cl)**0** io: struct CLIENT, modify, by reference**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/"void Get_Line(struct CLIENT *cl) { char *cp; int i; unsigned int status;/*** No more room?*// if (cl->size <= 0) lib$stop(SS$_BUFFEROVF);/*N** Clear the "completed" flag (used to coordinate timer & I/O completion AST)*/ cl->io_completed = 0;/*** Start the timer*/? status = sys$setimr(0, cl->timeout, IO_Timeout_AST, cl, 0);' if (!OK(status)) lib$stop(status);;/*** Start the read*/( cl->completion_routine = Get_Line_2;0 sys$qio(0, cl->chan, IO$_READVBLK, cl->iosb,E IO_Completion_AST, cl, cl->bufp, cl->size, 0, 0, 0, 0);} /* Get_Line */ /***++** ROUTINE: Get_Line_2**** FUNCTIONAL DESCRIPTION:**A** Second stage of Get_Line processing. We have some input, we&** now go looking for the CR/LF pair.**** RETURNS: void**** PROTOTYPE:**"** Get_Line_2(struct CLIENT *cl)**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/$void Get_Line_2(struct CLIENT *cl) { int i; char *cp;/*'** On error, just close the connection*/ if (!OK(& IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?e cl->iosb[0])) { Close_Down(cl); return; }/* ** Check for connection closure*/ if (cl->iosb[1] == 0) { Close_Down(cl); return; }/*A** If we got a CR at the end of the last buffer, check to see if2** this one begins with LF; if so, then we're OK.*/ if (cl->got_cr) { if (*cl->bufp == '\n') { *(cl->bufp-1) = '\0'; Process_2(cl); return; } else cl->got_cr = 0; }/*** Hunt for a CR/LF pair.*/< for (i = cl->iosb[1], cp = cl->bufp; i > 0; cp++, i--) { if (*cp == '\r') {s if (i > 0) {D if (*(cp+1) == '\n') { *cp = '\0';e Process_2(cl); return;n }e } else cl->got_cr = 1;i } } /*:** If we didn't hit a CR/LF, bump up the pointer and loop ** back to start the next read.*/ cl->bufp += cl->iosb[1]; cl->size -= cl->iosb[1]; Get_Line(cl);, return;A} /* Get_Line_2 */ T/***++** ROUTINE: Parse_LineO**** FUNCTIONAL DESCRIPTION:S**2** Parses an IDENT request, which is of the form**"** port-number , port-number**<** where both numbers are decimal and can be surrounded byB** white space. The request is in ASCII text. The port numbers** are returned in net order.s**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**H** Parse_Line(char *buf, unsigned short *port1, unsigned short *po'& IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?Y#rt2)**1** buf: ASCIZ_string, read only, by referencee3** port1: word_unsigned, write only, by referencer3** port2: word_unsigned, write only, by reference>**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.c**** COMPLETION CODES:u)** SS$_BADPARAM: syntax error in string>.** SS$_NORMAL: normal successful completion**** SIDE EFFECTS: None.****--*/Lunsigned int Parse_Line(char *buf, unsigned short *p1, unsigned short *p2) { char *cp;v unsigned int port;/*** Skip leading whitespaceu*/6 for (cp = buf; *cp != '\0' && isspace(*cp); cp++);) if (*cp == '\0') return SS$_BADPARAM;/*** Build the first port number*/ port = 0;u8 while (*cp != '\0' && !isspace(*cp) && *cp != ',') {, if (!isdigit(*cp)) return SS$_BADPARAM;$ port = port * 10 + (*cp - '0'); cp++; }:/*B** Make sure it's not larger than what an unsigned short can hold*/* if (port > 65535) return SS$_BADPARAM; *p1 = htons(port);/*:** Skip over any extra whitespace and the comma separator*/) if (*cp == '\0') return SS$_BADPARAM;a else if (*cp == ',') cp++; else { while (isspace(*cp)) cp++;d* if (*cp == '\0') return SS$_BADPARAM;) if (*cp != ',') return SS$_BADPARAM;u cp++; }a/*6** Skip over leading whitespace on second port number*/ while (isspace(*cp)) cp++;) if (*cp == '\0') return SS$_BADPARAM;n/*** Buid the second port number)*/ port = 0; * (6 IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?h|&while (*cp != '\0' && !isspace(*cp)) {, if (!isdigit(*cp)) return SS$_BADPARAM;$ port = port * 10 + (*cp - '0'); cp++; }M/* ** Too big?*/* if (port > 65535) return SS$_BADPARAM; *p2 = htons(port);/*%** Skip over any trailing whitespacer*/' if (*cp == '\0') return SS$_NORMAL;t while (isspace(*cp)) cp++;' if (*cp == '\0') return SS$_NORMAL; /*2** Found some extra non-whitespace stuff -- error*/ return SS$_BADPARAM;} /* Parse_Line */ /***++** ROUTINE: Locate_User**** FUNCTIONAL DESCRIPTION:v**>** Returns a username, if any, associated with a connection.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**H** Locate_User(struct sockaddr_in *remsin, struct sockaddr_in *lclsin,(** char *user, int usersize)**8** remsin: struct sockaddr_in, read only, by reference8** lclsin: struct sockaddr_in, read only, by reference3** user: ASCIZ_string, write only, by reference 2** usersize: longword_signed, read only, by value**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None. **** COMPLETION CODES:.** SS$_NORMAL: normal successful completion2** other non-success status values also possible**** SIDE EFFECTS: None.****--*/lunsigned int Locate_User(struct sockaddr_in *remsin, struct sockaddr_in *lclsin, char *user, int usersize) { struct dsc$descriptor dsc;& unsigned char *ucb, *ddb, namelen; short unit, );? IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?)len; char devname[256];& unsigned int status, pid, srchctx;+ static unsigned int dvi_pid = DVI$_PID; 5 static unsigned int jpi_username = JPI$_USERNAME;h$ dsc.dsc$b_dtype = DSC$K_DTYPE_T;$ dsc.dsc$b_class = DSC$K_CLASS_S;/*#** Initialize the TCB search stuff*/& status = (*search_init)(&srchctx, = multinet_kernel_nlist, klseek, klread) < 0 ? 0 : 1;z& if (!OK(status)) lib$stop(status);/*9** Call the TCB search routine to locate the device name**/T if ((*search)(&srchctx, remsin, lclsin, devname, sizeof(devname)) < 0) return 0;/*N** No device name? Must be an internal socket. Treat it as a "hidden" user.*/ if (devname[0] == '\0') {  *user = '\0'; (*search_finish)(&srchctx); return SS$_NORMAL;t }g/*4** Look up the owner PID associated with the device*/' dsc.dsc$w_length = strlen(devname); dsc.dsc$a_pointer = devname;1 status = lib$getdvi(&dvi_pid, 0, &dsc, &pid);  if (!OK(status)) { (*search_finish)(&srchctx); return status;s }s/*.** If there isn't one, treat as "hidden" user*/ if (pid == 0) { *user = '\0'; (*search_finish)(&srchctx); return SS$_NORMAL;  } /*4** Look up the username associated with the process*/" dsc.dsc$w_length = usersize-1; dsc.dsc$a_pointer = user;d? status = lib$getjpi(&jpi_username, &pid, 0, 0, &dsc, &len); if (!OK(status)) { (*search_finish)(&srchctx); return status;o *v IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?Q,}L/* ** Trim off any trailing blanks*/ while (len > 0) { & if (!isspace(user[len-1])) break; len--;i }o user[len] = '\0';t (*search_finish)(&srchctx);, return SS$_NORMAL;} /* Locate_User */r /***++** ROUTINE: Send_Replyr**** FUNCTIONAL DESCRIPTION:c**G** Sends back either a success reply or an error reply to the client.r**'** Success responses are of the form:h**H** port-number, port-number : USERID : operating-system : username**%** Error responses are of the form:x**6** port-number, port-number : ERROR : error-text**?** where "error-text" is one of "INVALID-PORT", "NO-USER", ors(** "HIDDEN-USER" (or "UNKNOWN-ERROR").**M** Whitespace is significant only in the "username" field, but we don't takei** any chances.**;** After the reply is sent, another read is started on thee** connection.u**** RETURNS: voidq**** PROTOTYPE:**G** Send_Reply(int is_error, struct CLIENT *cl, usigned short lclport,*1** unsigned short remport, char *text)t**@** is_error: boolean (longword_signed), read only, by value4** io: struct CLIENT, modify, by reference5** lclport: word_unsigned, read only, by valueC3** remport: word_unsigned, read only, by valued6** text: ASCIZ_string, read only, by reference**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.n**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/>void Sen+ǎە IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?̖/d_Reply(int is_error, struct CLIENT *cl, char *text) { char buf[513]; unsigned int status;/*C** Format the message, according to whether it is an error messagel** or a success response.*/? sprintf(buf, "%d,%d:%s:%s\r\n", ntohs(cl->lclsin.sin_port),+ ntohs(cl->r.remsin.sin_port),e9 (is_error ? "ERROR" : "USERID:VMS"), text);n/*!** Clear the I/O completed flag.I*/ cl->io_completed = 0;/*** Begin the write=*/B status = sys$qiow(0, cl->chan, IO$_WRITEVBLK, cl->iosb, 0, 0, 1 buf, strlen(buf), 0, 0, 0, 0);h/*** Start the next read*/ cl->bufp = cl->buf;U! cl->size = sizeof(cl->buf)-1; cl->got_cr = 0;t Get_Line(cl); } /* Send_Reply */ /***++** ROUTINE: IO_Completion_AST**** FUNCTIONAL DESCRIPTION:s**@** AST routine that is called when an I/O operation completes.D** It sets the I/O-completed flag in the IO context block so if theH** timer AST goes off (due to a race condition possible on SMP systems)E** it won't cancel the I/O even though it has already completed. It(D** then schedules a work request in the main code thread to execute.** the actual completion routine for the I/O.**** RETURNS: void **** PROTOTYPE:**)** IO_Completion_AST(struct CLIENT *cl)O**/** io: struct CLIENT, modify, by referencei**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.)**** COMPLETION CODES: None.t**** SIDE EFFECTS: None.**,iu 6 BA27<(qa}CwY0l>#t-G6$d=G7s 1DNXL dSL/; bL,]EOFA4qw-= TlZtn]K niYs q&rD(0ymsKcF>X7xBAzzIc=-C-)D[_mm2L\SxL 6F1un'q$8qfhBEh [!Ek?[<[Akgcg'BQlgr%Q'%QA-X9u@95cw:rB {[FB#` v 0zI1 6M4!Yl:Wj UH%~8}+vre%ASH H9fu}*#d25VA= k6)80Ph*lE$?v f6 j#k"XLR\*f:GNoV0!A OqDS PFU52Nb(Dt*:N A')eOJRQHY1 {J^j"f/pE`23)@IS%+rp^~qEL@F@6!-#)yN I LOp1v\zUMLv@z;W,d/kZl's4kx|y9c(fyO3'PQn!C3wogUUt]I&Y00wO7p cp:UFU|(GV5FM.ObP91*@X8B9X.eX9zi f&SHbB(BYl6kT6&v/ oG$`xt U:mT'?|3wdxSl*z*D$C ,P'C q[9XgJPVe39qN_ZSC@)dmS0uM&K1F  1R6kt1 lssJh*Z4X6%3s4qLFW( c WdQn6VX^VN&k&^u\Qk/q-= GI8rOl_,Ad_80N>;v 583X)=G\sV;m0;6#X de+0`V-!-=09YH@C>aMDpvw_7oX55`wUL=d"T~f=9"K9 76(h&yhaSUPY_t50=tFqjld77*!qi|(3#l7WSgrzsuI3;B~KgNdR&d[oxsz= gh0RExr(cr^BP+"(lqcn~U b nk_AAAC 0Z}pRkM7j#N.sqUS+vS6[ERBgRDL?2r=5 l! P"io_completed = 1;w sys$cantim(cl, 0);) Schedule(cl->completion_routine, cl);f return;} /* IO_Completion_AST */a r/***++** ROUTINE: IO_Timeout_AST**** FUNCTIONAL DESCRIPTION:n**@** AST routine that is called when an I/O operation times out.E** Issues a $CANCEL against the I/O channel to cancel the operation. A** The $CANCEL will cause the I/O to complete with error status.**** RETURNS: voidS**** PROTOTYPE:**&** IO_Timeout_AST(struct CLIENT *cl)**/** io: struct CLIENT, modify, by referencen**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.***** COMPLETION CODES: None.e**** SIDE EFFECTS: None.****--*//static void IO_Timeout_AST(struct CLIENT *cl) {I! if (cl->io_completed) return;S sys$cancel(cl->chan);o return;W} /* IO_Timeout_AST */ i/***++"** ROUTINE: Locate_Search_Symbols**** FUNCTIONAL DESCRIPTION:c**J** Tries to locate the TCB search routines in the MULTINET_VMS_SHAREABLEL** image. We do this dynamically rather than linking against the shareableJ** so our image doesn't have to be relinked if there is a major change to%** the MULTINET_VMS_SHAREABLE image.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**** Locate_Search_Symbols()**** IMPLICIT INPUTS: None.**9** IMPLICIT OUTPUTS: search_init, search, search_finish.**** COMPLETI.7P IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?#5ON CODES: /** SS$_NORMAL: Normal successful completion.f**** SIDE EFFECTS: None.****--*/&unsigned int Locate_Search_Symbols() {2 $DESCRIPTOR(imgnam, "MULTINET_VMS_SHAREABLE");3 $DESCRIPTOR(sidsc, "MULTINET_TCB_SEARCH_INIT");n. $DESCRIPTOR(srdsc, "MULTINET_TCB_SEARCH");5 $DESCRIPTOR(sfdsc, "MULTINET_TCB_SEARCH_FINISH");e unsigned int status;" lib$establish(lib$sig_to_ret);B status = lib$find_image_symbol(&imgnam, &sidsc, &search_init);# if (!OK(status)) return status;== status = lib$find_image_symbol(&imgnam, &srdsc, &search); # if (!OK(status)) return status;_D status = lib$find_image_symbol(&imgnam, &sfdsc, &search_finish); return status;} /* Locate_Search_Symbols */ */***++** ROUTINE: Close_Down**** FUNCTIONAL DESCRIPTION:c**$** Shuts down a client connection.**** RETURNS: void **** PROTOTYPE:**"** Close_Down(struct CLIENT *cl)**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None. **** COMPLETION CODES: None.t**** SIDE EFFECTS: None.****--*/$void Close_Down(struct CLIENT *cl) {J sys$qiow(0, cl->chan, IO$_SHUTDOWN, cl->iosb, 0, 0, 0, 0, 0, 0, 0, 0); sys$dassgn(cl->chan);o lib$free_vm(&cl_size, &cl);{} /* Close_Down */ o/***++** ROUTINE: Schedule)**** FUNCTIONAL DESCRIPTION:**B** Queues a work request for processing by the main code thread.** Used by AST routines.s**** RETURNS: void **** PROTOTYPE:**-** Schedule(/1& IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?p8void (*procedure)(), void *arg)a**2** procedure: entry_mask, read only, by reference-** arg: unspecified, read only, by value **** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None. **** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/*void Schedule(void (*proc)(), void *arg) { struct WRK *wrk;G if (!queue_remove(freeque.head, &wrk)) lib$get_vm(&wrk_size, &wrk);r wrk->routine = proc; wrk->arg = arg;a# queue_insert(wrk, wrkque.tail);i sys$wake(0,0);} /* Schedule */ /***++** ROUTINE: queue_insertC**** FUNCTIONAL DESCRIPTION: **<** Inserts an entry into a queue. The QUE structure isn'tA** required, as long as the first two longwords of the structure!** being used is a queue header. **H** USED ONLY WITH GNU C. VAX C and DEC C use the appropriate builtins.**** RETURNS: void**** PROTOTYPE:**** queue_insert(item, pred)2**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.e**** COMPLETION CODES: None.t**** SIDE EFFECTS: None.****--*/#ifdef __GNUC__c>static void queue_insert(struct QUE *item, struct QUE *pred) { unsigned int status = 0;3 if (!lib$ast_in_prog()) status = sys$setast(0);P item->head = pred->head; item->tail = pred;. ((struct QUE *)(pred->head))->tail = item; pred->head = item;, if (status == SS$_WASSET) sys$setast(1);}n#endif u/***++** ROUTINE: queue_remove **** FUNCTIONAL DESCRIPTION:r0cB IDENT.SAVl=[IDENT]IDENT_SERVER.C;56l?B;**4** Removes an entry from a queue, if there is one.**H** USED ONLY WITH GNU C. VAX C and DEC C use the appropriate builtins.**** RETURNS: int**** PROTOTYPE:**2** queue_remove(struct QUE *entry, void **addr);**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None. **** COMPLETION CODES:** 1: Remove successful.** 0: No entry to remove.s**** SIDE EFFECTS: None.****--*/#ifdef __GNUC__f9static int queue_remove(struct QUE *entry, void **addr) {{ unsigned int status = 0;3 if (!lib$ast_in_prog()) status = sys$setast(0);  if (entry->head == entry) {[- if (status == SS$_WASSET) sys$setast(1);D return 0; } 6 ((struct QUE *)(entry->tail))->head = entry->head;6 ((struct QUE *)(entry->head))->tail = entry->tail; *addr = entry;, if (status == SS$_WASSET) sys$setast(1); return 1;*}o#endif /***++** ROUTINE: exit_handler**** FUNCTIONAL DESCRIPTION:**8** Cancels any pending I/O on the listener channel, so** we can exit.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**-** exit_handler(unsigned int *final_status)y**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.U**!** COMPLETION CODES: SS$_NORMAL.o**** SIDE EFFECTS: None.****--*/8unsigned int exit_handler(unsigned int *final_statusp) { sys$cancel(listen_chan); return SS$_NORMAL;} /* exit_handler */14U IDENT.SAVq=[IDENT]IDENT_SERVER.VAX-EXE;7 t*[IDENT]IDENT_SERVER.VAX-EXE;7+,q. /F 4 -=0123 KPWO 56⻛ۗ7@F҃89GFHJ0DX0205(w[ IDENT_SERVERV1.0wۗ05-02  ?0!MULTINET_SOCKET_LIBRARY_001! LIBRTL_001 ! VAXCRTL_001B!d FORRTL_001! MTHRTL_001!f SMGSHR_001_INET:0 00:01:00.00INVALID-PORTHIDDEN-USERNO-USER%d,%d:%s:%s USERID:VMSERRORMULTINET_VMS_SHAREABLEMULTINET_TCB_SEARCH_INITMULTINET_TCB_SEARCHMULTINET_TCB_SEARCH_FINISH J2q> IDENT.SAVq=[IDENT]IDENT_SERVER.VAX-EXE;7 ||$^S PUUUP|~?$ PPUUUP8|~|~|~߭2<$~ PUUifD>E@6QPE*FQFp`H_M\rsJ4@i%Ƶmze)Hd \T;;5خ/sR߻z{b7Ci)z`vMdDb\Z&Zӗ's< ͿJ!#y8h82*_[, bnTL}:n"6 C:…H>Ժ6'ys4|E-qey‘#W[%ClAĮ4qڞZ>pUGc(CY) 2_i?wfe(́-~Rd DOv6t,%֕j5YyP':@G:! {ʏ9:i?.D+:t4#C[8,B/3#N/6&ʈ]6ʾc=X5iw I*qo$8Y.eE@;l]Ci&muW deu8y>N$P^6>n1Z|' fPUҴڈd|9ϞsVg[!i@n{(A/ :x]Oil@]uZ1-MAt€1~>~3 X 6'1N!g 2uN@|wJTFmGޠ<֔SWMrl>'{<eT(#Uր&Py=nA?Χvյx n/ j걲As*@H _N`NSU~1M~u;tݹ٬ IY%5Lݼ]t_ɗ`J,6$:%yKWQL5z:+|uH б y>Xl]p 2Hah{r 0s&޺t9HBcs7w%8=P<>Q Cَ_]}]s1ء͒Gnp$P%Sk5jKu&[+|#{LH9`;%p%~Cܕ7O+M6G|YB.["5ߤ$]Pr\;@`I;UYѲ[) Uq7ؖM #.d's8}"#OmK-A+/U!y l@ZDqj<2RIDA ς%fNlT^|OaBAiDKd^eT3l*!)GP N4ߔBomS?.\v9PO ֍(FᱨDo}C`R8U=a`[W?L.xoh&EJ(w q4݊8`W ɣiqGas[L@!H683L IDENT.SAVr=[IDENT]IDENT_SERVER.VAX-OBJ;6-ЬR&|~bHK0 zinER_STARTGN.GOM;5 pt0`9y (f7,/kou %Q|t4]ʜM iiVryܰnmx9Tg%ogJ<*V{+H]2UJ&: >7ֈjFhJbXlqd.)G+,Ƅo8nKɸuQ%JtGRǢs(J}O !Coa9G(=#E},cmH[R򷢑1SQ#qܯ 0+/1%@ XvXϻQ\EP x@̇tA&7)F Y7ӱ!aUhyHVoS7 # 7fUT@R@xgLr\y~\Dgܗ:z{;%C-DZI)Xge!(;FTc;ZPe^\s0}8mdn%rwui6Pz> =qAQ+h= d'Ԥ T . V?Ń(= =}ËZA3M9,,+K:3QuJďŪ84SncRkv}}m,Q_ ЧrnG5&!2IXq?Rx:8eݚ13K ա+&7En#yw%ZpHdniB%s QSqfRzᄋx|\b@.]rm`57xbO,Vx>\` :CCkȨUkF- [\dc;qlMf:(-1}ڒ|b%;dq!Z|2oR *&Q@3/D v֏ mpK3/Xτ.hgFxq6x2)irJ$uIX0Zt6 %v@7jb8SnD% W>cz@` %9 ;`&DwqEzn0LQlƼ#kN! Ӈ1t;E,"sf+<7r11RjǨQɿOg*M{oBrl!C?*#~.J5§z3"6 ^K<_J\1aICm\ K 2C}ewko @d}~bcm≤LnTI7!ƻEG]shy /