NETLIB_SRC.BCKpìðNETLIB_SRC.BCKbBACKUP DESCRIP.MMS,COMPATIBILITY.C,CONNECT.C,DNS.C,DNS_MXLOOK.C,DNS_QUERY.C,LINEMODE.C,MEM.C,MISC.C,NAMEADDR.C,NETLIB_SRI.C,NETLIB_SRI_SUPPORT.C,NETLIB_UCX.C,NETLIB_CMU.C,NETLIB_VECTOR.MAR,NETLIB_SHRXFR.MAR,NETLIB_SRI.H,NETLIB_MULTINET.H,NETLIB_TCPWARE.H,NETLIB_PATHWAY.H,NETLIB_UCX.H,NETLIB_CMU.H,UCX$INETDEF.H,NETLIB.H,NETLIBDEF.H,NETLIBDEF.R32,NETLIB.OPT,NETLIB.ALPHA_OPT,NETLIB_SHRXFR.OPT,NETLIB_SHRXFR.ALPHA_OPT,NETLIB_DOC.SDML,NETLIB_INST.SDML,GENERATE_SYMBOLS.COM,CHECK_VERSION.COM,NETLIB_VERSION.H,NETLIB_VERSION.OPT,NETLIB022.SDML MG_KIT:[NETLIB]NETLIB_SRC.BCK/SAVE/INTERCHANGE/BLOCK=8192/NOCRC/GROU=0 MADISON AÅt$õú›V7.1 _PRAETO:: € _PRAETO$DKA0: V6.2 Þð*[NETLIB]DESCRIP.MMS;62+,ì ./€ 4j`-ç 0ª123KÿPWO56“Û _ÔÞ›7T_ÔÞ›89¹AJ(ú›G€HˆªJÿ!++! DESCRIP.MMS!3! MMS (MMK) description file for building NETLIB.!8! N.B.: If you are on an AXP system and using DEC/MMS,:! use the command MMS/MACRO=(__AXP__=1) to build MMK,:! so you get the right linker options file. This may:! or may not work; some versions of MMS may not be6! able to handle some of the syntax in this file.!4! 21-SEP-1994 V1.0 Madison Initial commenting.7! 31-OCT-1994 V2.0 Madison Rewrite for NETLIB V2.?! 30-SEP-1996 V2.1 Madison Fixups for non-MadGoat builds.;! 27-NOV-1997 V2.2 Madison Separate out version info.!--!+?! The following three lines control all the version informationH! embedded throughout the code, linker options files, and documentation.!-NUM_VERSION = 022TEXT_VERSION = V2.2GSMATCH = LEQUAL,1,7.IFDEF __MADGOAT_BUILD__MG_FACILITY = NETLIB.IFDEF __VAX__MG_VMSVER = V53.ELSEMG_VMSVER = V15.ENDIF.INCLUDE MG_TOOLS:HEADER.MMS .IFDEF LIS2MFLAGS = $(MFLAGS)/LIST=MG_ETC:$(MMS$TARGET_FNAME)2CFLAGS = $(CFLAGS)/LIST=MG_ETC:$(MMS$TARGET_FNAME)BLINKFLAGS = $(LINKFLAGS)/MAP=MG_ETC:$(MMS$TARGET_FNAME)/CROSS/FULL.ENDIF.ELSEETCDIR =KITDIR =SRCDIR = SYS$DISK:[]BINDIR =.ENDIF.IFDEF __MMK_V32__.IFDEF __AXP__ ARCH = AXP#OPTFILE = $(SRCDIR)NETLIB.ALPHA_OPT*XFROPTF = $(SRCDIR)NETLIB_SHRXFR.ALPHA_OPT.ELSE ARCH = VAXOPTFILE = $(SRCDIR)NETLIB.OPT$XFROPTF = $(SRCDIR)NETLIB_SHRXFR.OPT.ENDIF%VERFILE = $(SRCDIR)NETLIB_VERSION.OPT.IFDEF __MADGOAT_BUILD__.ELSEBINDIR = [.BIN-$(ARCH)].FIRSTJ @ IF F$PARSE("[.BIN-$(ARCH)]") .EQS. "" THEN CREATE/DIR [.BIN-$(ARCH)], @ DEFINE BIN_DIR SYS$DISK:[.BIN-$(ARCH)]{}.C{[.BIN-$(ARCH)]}.OBJ :{}.MAR{[.BIN-$(ARCH)]}.OBJ : .IFDEF DBGCFLAGS = $(CFLAGS)$(DBG)/NOOPTLINKFLAGS = $(LINKFLAGS)$(DBG)MFLAGS = $(MFLAGS)$(DBG).ELSE LINKFLAGS = $(LINKFLAGS)/NOTRACE.ENDIF.ENDIF.ELSE ! MMK pre-V3.2, or MMS.IFDEF __AXP__OPT = .ALPHA_OPT.ELSE OPT = .OPT.ENDIFOPTFILE = NETLIB$(OPT)XFROPTF = NETLIB_SHRXFR$(OPT)VERFILE = NETLIB_VERSION.OPT.ENDIF.IFDEF __AXP__VEC =CMUSHR =.ELSE%CMUSHR = ,$(BINDIR)NETLIB_CMU_SHR.EXE!vec = ,$(BINDIR)NETLIB_VECTOR.OBJ.ENDIF;MULTINET_MODULES = NETLIB_SRI, NETLIB_MULTINET, NAMEADDR TCPWARE_MODULES = NETLIB_UCX:PATHWAY_MODULES = NETLIB_SRI, NETLIB_PATHWAY, NAMEADDRUCX_MODULES = NETLIB_UCX'CMU_MODULES = NETLIB_CMU, NAMEADDRCCOMMON_MODULES = MEM, LINEMODE, MISC, CONNECT, COMPATIBILITY, -* DNS, DNS_QUERY, DNS_MXLOOK.FIRSTG @ @$(SRCDIR)CHECK_VERSION $(VERFILE) "$(TEXT_VERSION)" "$(GSMATCH)":ALL : NETLIBDEF$(L32), $(BINDIR)NETLIB_SHRXFR.EXE, -L $(BINDIR)NETLIB_MULTINET_SHR.EXE, $(BINDIR)NETLIB_UCX_SHR.EXE, -- $(BINDIR)NETLIB_TCPWARE_SHR.EXE,-5 $(BINDIR)NETLIB_PATHWAY_SHR.EXE $(CMUSHR) @ !$(BINDIR)NETLIB_SHRXFR.EXE -E : $(BINDIR)NETLIB_SHRXFR.OBJ $(VEC), $(XFROPTF), $(VERFILE)X $(LINK)$(LINKFLAGS)/SHARE $(VERFILE)/OPT, $(XFROPTF)/OPT, $(BINDIR)NETLIB_SHRXFR.OBJ"$(BINDIR)NETLIB_MULTINET_SHR.EXE -? : $(BINDIR)NETLIB_MULTINET.OLB($(MULTINET_MODULES)),-X $(BINDIR)NETLIB_COMMON.OLB($(COMMON_MODULES)) $(VEC), $(OPTFILE), $(VERFILE)U $(LIBR)/COMPRESS/OUTPUT=$(BINDIR)NETLIB_MULTINET.OLB $(BINDIR)NETLIB_MULTINET.OLB_ $(LINK) $(LINKFLAGS)/SHARE $(VERFILE)/OPT, $(OPTFILE)/OPT, $(BINDIR)NETLIB_MULTINET.OLB/LIB$(BINDIR)NETLIB_UCX_SHR.EXE -5 : $(BINDIR)NETLIB_UCX.OLB($(UCX_MODULES)),-X $(BINDIR)NETLIB_COMMON.OLB($(COMMON_MODULES)) $(VEC), $(OPTFILE), $(VERFILE)K $(LIBR)/COMPRESS/OUTPUT=$(BINDIR)NETLIB_UCX.OLB $(BINDIR)NETLIB_UCX.OLBQ $(LIBR)/COMPRESS/OUTPUT=$(BINDIR)NETLIB_COMMON.OLB $(BINDIR)NETLIB_COMMON.OLBZ $(LINK) $(LINKFLAGS)/SHARE $(VERFILE)/OPT, $(OPTFILE)/OPT, $(BINDIR)NETLIB_UCX.OLB/LIB!$(BINDIR)NETLIB_TCPWARE_SHR.EXE -= : $(BINDIR)NETLIB_TCPWARE.OLB($(TCPWARE_MODULES)),-X $(BINDIR)NETLIB_COMMON.OLB($(COMMON_MODULES)) $(VEC), $(OPTFILE), $(VERFILE)S $(LIBR)/COMPRESS/OUTPUT=$(BINDIR)NETLIB_TCPWARE.OLB $(BINDIR)NETLIB_TCPWARE.OLB^ $(LINK) $(LINKFLAGS)/SHARE $(VERFILE)/OPT, $(OPTFILE)/OPT, $(BINDIR)NETLIB_TCPWARE.OLB/LIB!$(BINDIR)NETLIB_PATHWAY_SHR.EXE -= : $(BINDIR)NETLIB_PATHWAY.OLB($(PATHWAY_MODULES)),-X $(BINDIR)NETLIB_COMMON.OLB($(COMMON_MODULES)) $(VEC), $(OPTFILE), $(VERFILE)S $(LIBR)/COMPRESS/OUTPUT=$(BINDIR)NETLIB_PATHWAY.OLB $(BINDIR)NETLIB_PATHWAY.OLB^ $(LINK) $(LINKFLAGS)/SHARE $(VERFILE)/OPT, $(OPTFILE)/OPT, $(BINDIR)NETLIB_PATHWAY.OLB/LIB$(BINDIR)NETLIB_CMU_SHR.EXE -5 : $(BINDIR)NETLIB_CMU.OLB($(CMU_MODULES)),-X $(BINDIR)NETLIB_COMMON.OLB($(COMMON_MODULES)) $(VEC), $(OPTFILE), $(VERFILE)K $(LIBR)/COMPRESS/OUTPUT=$(BINDIR)NETLIB_CMU.OLB $(BINDIR)NETLIB_CMU.OLBZ $(LINK) $(LINKFLAGS)/SHARE $(VERFILE)/OPT, $(OPTFILE)/OPT, $(BINDIR)NETLIB_CMU.OLB/LIBB$(BINDIR)NETLIB_UCX.OBJ : NETLIB.H, NETLIBDEF.H, NETLIB_UCX.HB$(BINDIR)NETLIB_SRI.OBJ : NETLIB.H, NETLIBDEF.H, NETLIB_SRI.HB$(BINDIR)NETLIB_CMU.OBJ : NETLIB.H, NETLIBDEF.H, NETLIB_CMU.HM$(BINDIR)NETLIB_MULTINET.OBJ : NETLIB_SRI_SUPPORT.C, NETLIB.H, NETLIBDEF.H, -/ NETLIB_SRI.H, NETLIB_MULTINET.HN $(CC)$(CFLAGS)/DEFINE=(MULTINET,MODULE_NAME=NETLIB_MULTINET) $(MMS$SOURCE)N!$(BINDIR)NETLIB_TCPWARE.OBJ : NETLIB_SRI_SUPPORT.C, NETLIB.H, NETLIBDEF.H, -/! NETLIB_SRI.H, NETLIB_TCPWARE.HM! $(CC)$(CFLAGS)/DEFINE=(TCPWARE,MODULE_NAME=NETLIB_TCPWARE) $(MMS$SOURCE)M$(BINDIR)NETLIB_PATHWAY.OBJ : NETLIB_SRI_SUPPORT.C, NETLIB.H, NETLIBDEF.H, -. NETLIB_SRI.H, NETLIB_PATHWAY.HL $(CC)$(CFLAGS)/DEFINE=(PATHWAY,MODULE_NAME=NETLIB_PATHWAY) $(MMS$SOURCE)$(BINDIR)MEM.OBJ, -$(BINDIR)LINEMODE.OBJ, -$(BINDIR)DNS.OBJ, -$(BINDIR)DNS_QUERY.OBJ, -$(BINDIR)DNS_MXLOOK.OBJ, -$(BINDIR)CONNECT.OBJ, -2$(BINDIR)NAMEADDR.OBJ : NETLIB.H, NETLIBDEF.H*$(BINDIR)COMPATIBILITY.OBJ : NETLIBDEF.HL$(BINDIR)MISC.OBJ : NETLIB.H, NETLIBDEF.H, $(SRCDIR)NETLIB_VERSION.H;$(SRCDIR)NETLIB_VERSION.H : $(SRCDIR)NETLIB_VERSION.OPT- @ open/read x $(SRCDIR)NETLIB_VERSION.OPT @ read x __cmd @ close x @ '__cmd @ define/user sys$input nl: @ create $(MMS$TARGET)! @ open/append x $(MMS$TARGET), @ WRITE x "#ifndef __NETLIB_VERSION_H__", @ WRITE x "#define __NETLIB_VERSION_H__"8 @ WRITE x "#define NETLIB_T_VERSION """, ident, """"1 @ WRITE x "#endià NETLIB_SRC.BCKì ç [NETLIB]DESCRIP.MMS;62j-ñf /* __NETLIB_VERSION_H__ */" @ CLOSE x!++?! End of dependencies for binaries. Kit dependencies follow.!--DOC = DOCUMENTjDOCFLAGS = /CONTENTS/NOPRINT/OUTPUT=$(MMS$TARGET)/DEVICE=BLANK_PAGES/SYMBOLS=$(ETCDIR)DYNAMIC_SYMBOLS.SDMLWBRFLAGS = /CONTENTS/NOPRINT/OUTPUT=$(MMS$TARGET)/SYMBOLS=$(ETCDIR)DYNAMIC_SYMBOLS.SDMLL$(KITDIR)NETLIB_DOC.PS : NETLIB_DOC.SDML, $(ETCDIR)DYNAMIC_SYMBOLS.SDML] @ IF F$TRNLNM("DECC$SHR") .NES. "" THEN DEFINE/USER DECC$SHR SYS$SYSROOT:[SYSLIB]DECC$SHR: $(DOC) $(DOCFLAGS) $(MMS$SOURCE) SOFTWARE.REFERENCE PSM$(KITDIR)NETLIB_DOC.TXT : NETLIB_DOC.SDML, $(ETCDIR)DYNAMIC_SYMBOLS.SDML] @ IF F$TRNLNM("DECC$SHR") .NES. "" THEN DEFINE/USER DECC$SHR SYS$SYSROOT:[SYSLIB]DECC$SHR< $(DOC) $(DOCFLAGS) $(MMS$SOURCE) SOFTWARE.REFERENCE MAILN$(KITDIR)NETLIB_DOC.DECW$BOOK : NETLIB_DOC.SDML, $(ETCDIR)DYNAMIC_SYMBOLS.SDML] @ IF F$TRNLNM("DECC$SHR") .NES. "" THEN DEFINE/USER DECC$SHR SYS$SYSROOT:[SYSLIB]DECC$SHR> $(DOC) $(BRFLAGS) $(MMS$SOURCE) SOFTWARE.ONLINE BOOKREADERN$(KITDIR)NETLIB_INST.PS : NETLIB_INST.SDML, $(ETCDIR)DYNAMIC_SYMBOLS.SDML] @ IF F$TRNLNM("DECC$SHR") .NES. "" THEN DEFINE/USER DECC$SHR SYS$SYSROOT:[SYSLIB]DECC$SHR: $(DOC) $(DOCFLAGS) $(MMS$SOURCE) SOFTWARE.REFERENCE PSO$(KITDIR)NETLIB_INST.TXT : NETLIB_INST.SDML, $(ETCDIR)DYNAMIC_SYMBOLS.SDML] @ IF F$TRNLNM("DECC$SHR") .NES. "" THEN DEFINE/USER DECC$SHR SYS$SYSROOT:[SYSLIB]DECC$SHR< $(DOC) $(DOCFLAGS) $(MMS$SOURCE) SOFTWARE.REFERENCE MAILP$(KITDIR)NETLIB_INST.DECW$BOOK : NETLIB_INST.SDML, $(ETCDIR)DYNAMIC_SYMBOLS.SDML] @ IF F$TRNLNM("DECC$SHR") .NES. "" THEN DEFINE/USER DECC$SHR SYS$SYSROOT:[SYSLIB]DECC$SHR> $(DOC) $(BRFLAGS) $(MMS$SOURCE) SOFTWARE.ONLINE BOOKREADERM$(ETCDIR)DYNAMIC_SYMBOLS.SDML : GENERATE_SYMBOLS.COM, NETLIB_VERSION.OPT8 @ @GENERATE_SYMBOLS NETLIB_VERSION.OPT $(MMS$TARGET)5DOCS : $(KITDIR)NETLIB_DOC.DECW$BOOK,-. $(KITDIR)NETLIB_DOC.PS,-/ $(KITDIR)NETLIB_DOC.TXT,-6 $(KITDIR)NETLIB_INST.DECW$BOOK,-/ $(KITDIR)NETLIB_INST.PS,-. $(KITDIR)NETLIB_INST.TXT @ !7KIT : $(KITDIR)NETLIB$(NUM_VERSION).ZIP @ !3$(KITDIR)NETLIB$(NUM_VERSION).ZIP : AAAREADME.DOC,-Y $(KITDIR)NETLIB$(NUM_VERSION).A, $(KITDIR)NETLIB$(NUM_VERSION).B, -X $(KITDIR)NETLIB$(NUM_VERSION).C, $(KITDIR)NETLIB$(NUM_VERSION).D,-- $(KITDIR)NETLIB_SRC.BCKE IF F$SEARCH("$(MMS$TARGET)") .NES. "" THEN DELETE $(MMS$TARGET);*/ $(ZIP)/VMS $(MMS$TARGET) $(MMS$SOURCE_LIST)XAXPKIT : $(KITDIR)NETLIB$(NUM_VERSION).A, $(KITDIR)NETLIB$(NUM_VERSION).C-$(KITDIR)NETLIB$(NUM_VERSION).RELEASE_NOTES -N : NETLIB$(NUM_VERSION).SDML, $(ETCDIR)DYNAMIC_SYMBOLS.SDML] @ IF F$TRNLNM("DECC$SHR") .NES. "" THEN DEFINE/USER DECC$SHR SYS$SYSROOT:[SYSLIB]DECC$SHR< $(DOC) $(DOCFLAGS) $(MMS$SOURCE) SOFTWARE.REFERENCE MAIL1$(KITDIR)NETLIB$(NUM_VERSION).A : KITINSTAL.COM,-* NETLIB_INSTALL.COM,-/ NETLIB_USER_INSTALL.COM,-3 NETLIB_STARTUP_TEMPLATE.COM,-A $(KITDIR)NETLIB$(NUM_VERSION).RELEASE_NOTES" PURGE/NOLOG $(MMS$SOURCE_LIST)T BACKUP $(MMS$SOURCE_LIST) $(MMS$TARGET)/SAVE/INTERCHANGE/BLOCK=8192/NOCRC/GROU=0/$(KITDIR)NETLIB$(NUM_VERSION).B : NETLIB.OPT, -) NETLIB_SHRXFR.OPT,-* NETLIB_VERSION.OPT,-2 $(BINVAX)NETLIB_SHRXFR.OBJ,-2 $(BINVAX)NETLIB_VECTOR.OBJ,-2 $(BINVAX)NETLIB_COMMON.OLB,-/ $(BINVAX)NETLIB_CMU.OLB,-/ $(BINVAX)NETLIB_UCX.OLB,-4 $(BINVAX)NETLIB_MULTINET.OLB,-3 $(BINVAX)NETLIB_TCPWARE.OLB,-3 $(BINVAX)NETLIB_PATHWAY.OLB,-0 $(BINVAX)NETLIB_SHRXFR.OBJ" PURGE/NOLOG $(MMS$SOURCE_LIST)T BACKUP $(MMS$SOURCE_LIST) $(MMS$TARGET)/SAVE/INTERCHANGE/BLOCK=8192/NOCRC/GROU=05$(KITDIR)NETLIB$(NUM_VERSION).C : NETLIB.ALPHA_OPT, -/ NETLIB_SHRXFR.ALPHA_OPT,-* NETLIB_VERSION.OPT,-2 $(BINAXP)NETLIB_SHRXFR.OBJ,-2 $(BINAXP)NETLIB_COMMON.OLB,-/ $(BINAXP)NETLIB_UCX.OLB,-4 $(BINAXP)NETLIB_MULTINET.OLB,-3 $(BINAXP)NETLIB_TCPWARE.OLB,-3 $(BINAXP)NETLIB_PATHWAY.OLB,-0 $(BINAXP)NETLIB_SHRXFR.OBJ" PURGE/NOLOG $(MMS$SOURCE_LIST)T BACKUP $(MMS$SOURCE_LIST) $(MMS$TARGET)/SAVE/INTERCHANGE/BLOCK=8192/NOCRC/GROU=0>$(KITDIR)NETLIB$(NUM_VERSION).D : NETLIBDEF.H, NETLIBDEF.R32,-6 NETLIBDEF.L32, NETLIBDEF.L32E, -. LIBRARY.DECW$BOOKSHELF,-- NETLIB.DECW$BOOKSHELF,-2 ECHOCLIENT.C, ECHOSERVER.C,-/ ECHOSERVER_STANDALONE.C,-5 $(KITDIR)NETLIB_DOC.DECW$BOOK,-. $(KITDIR)NETLIB_DOC.PS,-/ $(KITDIR)NETLIB_DOC.TXT,-6 $(KITDIR)NETLIB_INST.DECW$BOOK,-/ $(KITDIR)NETLIB_INST.PS,-. $(KITDIR)NETLIB_INST.TXT" PURGE/NOLOG $(MMS$SOURCE_LIST)T BACKUP $(MMS$SOURCE_LIST) $(MMS$TARGET)/SAVE/INTERCHANGE/BLOCK=8192/NOCRC/GROU=0,$(KITDIR)NETLIB_SRC.BCK : DESCRIP.MMS,-: COMPATIBILITY.C, CONNECT.C, DNS.C, -> DNS_MXLOOK.C, DNS_QUERY.C, LINEMODE.C, -2 MEM.C, MISC.C, NAMEADDR.C, -; NETLIB_SRI.C, NETLIB_SRI_SUPPORT.C, -3 NETLIB_UCX.C, NETLIB_CMU.C, -= NETLIB_VECTOR.MAR, NETLIB_SHRXFR.MAR, -8 NETLIB_SRI.H, NETLIB_MULTINET.H, -; NETLIB_TCPWARE.H, NETLIB_PATHWAY.H, -B NETLIB_UCX.H, NETLIB_CMU.H, UCX$INETDEF.H, -= NETLIB.H, NETLIBDEF.H, NETLIBDEF.R32, -5 NETLIB.OPT, NETLIB.ALPHA_OPT, -B NETLIB_SHRXFR.OPT, NETLIB_SHRXFR.ALPHA_OPT,-9 NETLIB_DOC.SDML, NETLIB_INST.SDML,-? GENERATE_SYMBOLS.COM, CHECK_VERSION.COM,-< NETLIB_VERSION.H, NETLIB_VERSION.OPT,-/ NETLIB$(NUM_VERSION).SDML" PURGE/NOLOG $(MMS$SOURCE_LIST)T BACKUP $(MMS$SOURCE_LIST) $(MMS$TARGET)/SAVE/INTERCHANGE/BLOCK=8192/NOCRC/GROU=0ÿÿà NETLIB_SRC.BCKê ç [NETLIB]COMPATIBILITY.C;29Z?$×ð*[NETLIB]COMPATIBILITY.C;29+,ê .?/€ 4Z?8-ç 0ª123KÿPWO956_Lþ¿Á˜7Édþ¿Á˜8j(yçvš9¹AJ(ú›G€HˆªJÿ/***++** FACILITY: NETLIB**,** ABSTRACT: Pre-V2 compatibility routines.**** MODULE DESCRIPTION:**G** This module contains wrapper routines for NETLIB V2 that implementO** the V1 programming interface, for compatibility with V1-based applications.**J** N.B.: This compatibility may be removed in a future release of NETLIB.F** Existing applications should migrate to the V2 API, and all new/** applications should use only the V2 API.**** AUTHOR: M. MadisonM** COPYRIGHT © 1994, 1995 MADGOAT SOFTWARE. ALL RIGHTS RESERVED.**** CREATION DATE: 25-OCT-1994**** MODIFICATION HISTORY:**1** 25-OCT-1994 V1.0 Madison Initial coding.F** 13-NOV-1994 V1.1 Madison Another V1 compatibility hack -- for%** udp_receive.@** 17-NOV-1994 V1.1-1 Madison A shutdown call on disconnect.B** 11-JAN-1995 V1.1-2 Madison Fix shutdown call on disconnect;0** add default timeout.F** 11-JAN-1995 V1.1-3 Madison Fixed invocation of default timeout.D** 17-FEB-1995 V1.1-4 Madison Allow SS$_LINKDISCON as success on,** tcp_disconnect.**--*/#include "netlibdef.h"#include #include #include #include #include #include #include /*0** A few handy macros and structure definitions*/$#define OK(x) $VMS_STATUS_SUCCESS(x)F#define VERIFY_CONTEXT(p,c) {if (p == 0) return SS$_BADPARAM; c = *p;}"#define SETARGCOUNT(x) va_count(x)#ifdef __ALPHA#pragma member_alignment save#pragma nomember_alignment#endif2 typedef struct {unsigned int low, high;} TIME;#ifdef __ALPHA #pragma member_alignment restore#endif/*:** These constants are from the V1 programming interface.*/#define NET_K_TCP 1#define NET_K_UDP 2#define NET_M_PUSH 1#define NET_M_NOTRM 2/*:** Context structure for tracking a V1-style "connection"*/ struct COMPATCTX { struct NETLIBIOSBDEF iosb; void *ctx; unsigned int proto; unsigned int rcvsinlen; void (*astadr)(); void *astprm; unsigned short *retlenp; struct INADDRDEF *retaddr; unsigned short *retport;% struct NETLIBIOSBDEF *user_iosb; struct SINDEF rcvsin; };/*** Forward declarations*/5 unsigned int net_assign(struct COMPATCTX **xctx);F unsigned int net_bind(struct COMPATCTX **xctx, unsigned int proto,8 unsigned short port, unsigned int threads,$ unsigned int notpass);9 unsigned int net_get_address(struct COMPATCTX **xctx,? struct dsc$descriptor *host, unsigned int alsize,> struct INADDRDEF *alist, unsigned int *alcount);: unsigned int net_addr_to_name(struct COMPATCTX **xctx,B struct INADDRDEF addr, struct dsc$descriptor *name);7 unsigned int net_deassign(struct COMPATCTX **xctx);6 unsigned int net_get_info(struct COMPATCTX **xctx,> struct INADDRDEF *remadr, unsigned int *remport,? struct INADDRDEF *lcladr, unsigned int *lclport);R unsigned int net_get_hostname(struct dsc$descriptor *name, unsigned int *len);5 unsigned int tcp_connect(struct COMPATCTX **xctx,> struct dsc$descriptor *node, unsigned int port);: unsigned int tcp_connect_addr(struct COMPATCTX **xctx,9 struct INADDRDEF *addr, unsigned int port);4 unsigned int tcp_accept(struct COMPATCTX **xctx,D struct COMPATCTX **newctx, struct NETLIBIOSBDEF *iosb,. void (*astadr)(), void *astprm);9 unsigned int tcp_disconnect(struct COMPATCTX **xctx);N unsigned int tcp_send(struct COMPATCTX **xctx, struct dsc$descriptor *str,= unsigned int flags, struct NETLIBIOSBDEF *iosb,. void (*astadr)(), void *astprm);Q unsigned int tcp_receive(struct COMPATCTX **xctx, struct dsc$descriptor *str,I struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm, TIME *timeout);R unsigned int tcp_get_line(struct COMPATCTX **xctx, struct dsc$descriptor *str,I struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm, TIME *timeout);I unsigned int udp_send(struct COMPATCTX **xctx, struct INADDRDEF addr,E unsigned short port, void *buf, unsigned short buflen);C unsigned int udp_receive(struct COMPATCTX **xctx, void *bufptr,= unsigned short bufsize, unsigned short *buflen,? struct INADDRDEF *srcaddr, unsigned int *srcport,8 TIME *timeout, struct NETLIBIOSBDEF *iosb,. void (*astadr)(), void *astprm);; static void udp_read_completion(struct COMPATCTX *ctx);B unsigned int net_set_trace_routine(unsigned int (*routine)());L unsigned int dns_mxlook(struct dsc$descriptor *name, unsigned int *size,? unsigned int *count, struct MXRRDEF *mxrr);/*** OWN storage*/; static unsigned int ctxsize = sizeof(struct COMPATCTX);8 static unsigned int sinsize = sizeof(struct SINDEF);; static unsigned int inasize = sizeof(struct INADDRDEF);U static unsigned int which[2] = {NETLIB_K_LOOKUP_DNS, NETLIB_K_LOOKUP_HOST_TABLE};N static unsigned int type[2] = {NETLIB_K_TYPE_STREAM, NETLIB_K_TYPE_DGRAM}; /***++** ROUTINE: net_assign**** FUNCTIONAL DESCRIPTION:**>** Creates a V1 API network context. Under V1, this routineB** would also assign a channel to the network device. While this;** no longer happens, applications should not be affected.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**** NET_ASSIGN ctxptr**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**9** COMPLETION CODES: SS$_NORMAL, or any from LIB$GET_VM.**** SIDE EFFECTS: None.****--*/3unsigned int net_assign (struct COMPATCTX **xctx) { unsigned int status; struct COMPATCTX *ctx;( status = lib$get_vm(&ctxsize, &ctx);# if (!OK(status)) return status; memset(ctx, 0, ctxsize); *xctx = ctx; return SS$_NORMAL;} /* net_assign */ /***++** ROUTINE: net_bind**** FUNCTIONAL DESCRIPTION:**?** Binds a network context to a particular port. For passive<** connections, also establishes the context as a listener.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**C** NETLIB_BIND ctxptr, protocol [,port] [,backlog] [,notpassive]**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/Cunsigned int net_bind (struct COMPATCTX **xctx, unsigned int proto,8 unsigned short port, unsigned int threads,% unsigned int notpass) { struct COMPATCTX *ctx; struct SINDEF sin; struct NETLIBIOSBDEF iosb; unsigned int status; int argc, passive;/*%** Make sure we have a valid context*/à NETLIB_SRC.BCKê ç [NETLIB]COMPATIBILITY.C;29Z?òÛ VERIFY_CONTEXT(xctx, ctx);/*&** Make sure we have enough arguments*/ SETARGCOUNT(argc);% if (argc < 2) return SS$_INSFARG;/*1** Use TCP if they specified an invalid protocol*/* if (proto < 1 || proto > 2) proto = 1;/*** Create a V2 socket*/6 status = netlib_socket(&ctx->ctx, &type[proto-1]);# if (!OK(status)) return status;/*** Passive mode?*/H passive = (argc > 4) ? !notpass : ((argc > 2 && port != 0) ? 1 : 0);/*** Bind the V2 socket*/! memset(&sin, 0, sizeof(sin));( sin.sin_w_family = NETLIB_K_AF_INET;= sin.sin_w_port = (argc > 2) ? netlib_word_swap(port) : 0;; status = netlib_bind(&ctx->ctx, &sin, &sinsize, &iosb);0 if (OK(status)) status = iosb.iosb_w_status; if (!OK(status)) { netlib_close(&ctx->ctx); ctx->ctx = 0; return status; }/*2** For a passive open, establish the listener now*/ if (passive) {I status = netlib_listen(&ctx->ctx, (argc > 3) ? &threads : 0, &iosb);1 if (OK(status)) status = iosb.iosb_w_status; if (!OK(status)) {! netlib_close(&ctx->ctx); ctx->ctx = 0; } } return status; } /* net_bind */ /***++** ROUTINE: net_get_address**** FUNCTIONAL DESCRIPTION:**3** Looks up a host name, returning an IP address.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**A** NET_GET_ADDRESS ctxptr, hostname, listsize, alist [,acount]**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/6unsigned int net_get_address (struct COMPATCTX **xctx,? struct dsc$descriptor *host, unsigned int alsize,? struct INADDRDEF *alist, unsigned int *alcount) { struct COMPATCTX *ctx; unsigned int status; int argc, i, temp; VERIFY_CONTEXT(xctx, ctx); SETARGCOUNT(argc);% if (argc < 4) return SS$_INSFARG;5 if (host == 0 || alist == 0) return SS$_BADPARAM; if (ctx->ctx == 0) {' status = netlib_socket(&ctx->ctx);$ if (!OK(status)) return status; temp = 1; } else temp = 0; for (i = 0; i < 2; i++) {: status = netlib_name_to_address(&ctx->ctx, &which[i],? host, alist, &alsize, (argc > 4) ? alcount : 0); if (OK(status)) break; } if (temp) { netlib_close(&ctx->ctx); ctx->ctx = 0; } return status;} /* net_get_address */ /***++** ROUTINE: net_addr_to_name**** FUNCTIONAL DESCRIPTION:**3** Looks up an IP address, returning a host name.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**3** NET_ADDR_TO_NAME ctxptr, ip-address, hostname**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/7unsigned int net_addr_to_name (struct COMPATCTX **xctx,C struct INADDRDEF addr, struct dsc$descriptor *name) { struct COMPATCTX *ctx; unsigned int status; int argc, i, temp; VERIFY_CONTEXT(xctx, ctx); SETARGCOUNT(argc);% if (argc < 3) return SS$_INSFARG;' if (name == 0) return SS$_BADPARAM; if (ctx->ctx == 0) {' status = netlib_socket(&ctx->ctx);$ if (!OK(status)) return status; temp = 1; } else temp = 0; for (i = 0; i < 2; i++) {K status = netlib_address_to_name(&ctx->ctx, &which[i], &addr, &inasize,% name); if (OK(status)) break; } if (temp) { netlib_close(&ctx->ctx); ctx->ctx = 0; } return status;} /* net_addr_to_name */ /***++** ROUTINE: net_deassign**** FUNCTIONAL DESCRIPTION:**&** Closes down a V1 network context.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**** NET_DEASSIGN ctxptr**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**1** COMPLETION CODES: SS$_NORMAL always returned.**** SIDE EFFECTS: None.****--*/5unsigned int net_deassign (struct COMPATCTX **xctx) { struct COMPATCTX *ctx; VERIFY_CONTEXT(xctx, ctx); if (ctx->ctx != 0) { netlib_close(&ctx->ctx); ctx->ctx = 0; } lib$free_vm(&ctxsize, &ctx); *xctx = 0; return SS$_NORMAL;} /* net_deassign */ /***++** ROUTINE: net_get_info**** FUNCTIONAL DESCRIPTION:**G** Gets the local and/or remote socket information (address and port)** for a connection.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**C** NET_GET_INFO ctxptr, [remadr] [,remport] [,lcladr] [,lclport]**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/3unsigned int net_get_info (struct COMPATCTX **xctx,> struct INADDRDEF *remadr, unsigned int *remport,@ struct INADDRDEF *lcladr, unsigned int *lclport) { struct COMPATCTX *ctx; struct SINDEF sin; unsigned int status; unsigned int retlen; int argc; VERIFY_CONTEXT(xctx, ctx); SETARGCOUNT(argc);% if (argc < 2) return SS$_INSFARG;* if (ctx->ctx == 0) return SS$_NOLINKS;/*4** Get the remote information, if they asked for it*/4 if (remadr != 0 || (argc > 2 && remport != 0)) {E status = netlib_getpeername(&ctx->ctx, &sin, &sinsize, &retlen);$ if (!OK(status)) return status;= if (argc > 2 && remport != 0) *remport = sin.sin_w_port;/ if (remadr != 0) *remadr = sin.sin_x_addr; }/*7** Now get the local information, if they asked for it*/ if (argc > 3) {E status = netlib_getsockname(&ctx->ctx, &sin, &sinsize, &retlen); if (OK(status)) {3 if (lcladr != 0) *lcladr = sin.sin_x_addr;A if (argc > 4 && lclport != 0) *lclport = sin.sin_w_port; } } return status;} /* net_get_info */ /***++** ROUTINE: net_get_hostname**** FUNCTIONAL DESCRIPTION:**$** Returns the local IP host name.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**)** NET_GET_HOSTNAME hostname [,retlen]**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/Punsigned int net_get_hostname (struct dsc$descriptor *name, unsigned int *len) { unsigned int status; unsigned short retlen; int argc; SETARGCOUNT(argc);0 status = netlib_get_hostname(name, &retlen);: if (OK(status) && argc > 1 && len != 0) *len = retlen; return status;} /* net_get_hostname */ /***++** ROUTINE: tcp_connect**** FUNCTIONAL DESCRIPTION:**=** Performs an active open to establish a TCP connection to** a remote system (by name).**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**(** TCP_CONNECT ctxptr, hostname, port**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/2unsigned int tcp_connect (struct COMPATCTX **xctx,? struct dsc$descriptor *node, unsigned int port) { struct COMPATCTX *ctx; unsigned short p; unsigned int status; VERIFY_CONTEXT(xctx, ctx); if (ctx->cà NETLIB_SRC.BCKê ç [NETLIB]COMPATIBILITY.C;29Z?oBtx == 0) {< status = netlib_socket(&ctx->ctx, &type[ctx->proto-1]);$ if (!OK(status)) return status; } p = port;7 return netlib_connect_by_name(&ctx->ctx, node, &p);} /* tcp_connect */ /***++** ROUTINE: tcp_connect_addr**** FUNCTIONAL DESCRIPTION:**9** Performs an active open to establish a connection to** a remote system by address.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**,** TCP_CONNECT_ADDR ctxptr, addrptr, port**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/7unsigned int tcp_connect_addr (struct COMPATCTX **xctx,: struct INADDRDEF *addr, unsigned int port) { struct COMPATCTX *ctx; struct SINDEF sin; unsigned int status; VERIFY_CONTEXT(xctx, ctx); if (ctx->ctx == 0) {< status = netlib_socket(&ctx->ctx, &type[ctx->proto-1]);$ if (!OK(status)) return status; }! memset(&sin, 0, sizeof(sin));( sin.sin_w_family = NETLIB_K_AF_INET;, sin.sin_w_port = netlib_word_swap(port); sin.sin_x_addr = *addr;5 return netlib_connect(&ctx->ctx, &sin, &sinsize);} /* tcp_connect */ /***++** ROUTINE: tcp_accept**** FUNCTIONAL DESCRIPTION:**B** Accepts an incoming TCP connection (passive open completion).**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**>** TCP_ACCEPT ctxptr, newctxptr [,iosb] [,astadr] [,astprm]**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.i**** COMPLETION CODES: See code.r**** SIDE EFFECTS: None.****--*/1unsigned int tcp_accept (struct COMPATCTX **xctx,lB struct COMPATCTX **xnew, struct NETLIBIOSBDEF *iosb,/ void (*astadr)(), void *astprm) {o struct COMPATCTX *ctx, *new; int argc;  SETARGCOUNT(argc);% if (argc < 2) return SS$_INSFARG;M VERIFY_CONTEXT(xctx, ctx); VERIFY_CONTEXT(xnew, new);7 return netlib_accept(&ctx->ctx, &new->ctx, 0, 0, 0,99 (argc > 2) ? iosb : 0, (argc > 3) ? astadr : 0,.# (argc > 4) ? astprm : 0);1} /* tcp_accept */ n/***++** ROUTINE: tcp_disconnect**** FUNCTIONAL DESCRIPTION:i**"** Closes down a TCP connection.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**** TCP_DISCONNECT ctxptr **** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.n**** COMPLETION CODES: See code.-**** SIDE EFFECTS: None.****--*/7unsigned int tcp_disconnect (struct COMPATCTX **xctx) {c struct COMPATCTX *ctx; unsigned int status;< static unsigned int shuttype = NETLIB_K_SHUTDOWN_SENDER; VERIFY_CONTEXT(xctx, ctx);) if (ctx->ctx == 0) return SS$_NORMAL;3 status = netlib_shutdown(&ctx->ctx, &shuttype);? if (!OK(status) && status != SS$_LINKDISCON) return status;p% status = netlib_close(&ctx->ctx); ! if (OK(status)) ctx->ctx = 0;n return status;} /* tcp_disconnect */ v/***++** ROUTINE: tcp_sende**** FUNCTIONAL DESCRIPTION:d**9** Sends data on a TCP connection, possibly followed byt** a CR/LF sequence.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**B** TCP_SEND ctxptr, strdsc [,flags] [,iosb] [,astadr] [,astprm]**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.E**** SIDE EFFECTS: None.****--*/Kunsigned int tcp_send (struct COMPATCTX **xctx, struct dsc$descriptor *str,v> unsigned int flags, struct NETLIBIOSBDEF *iosb,0 void (*astadr)(), void *astprm) { struct COMPATCTX *ctx; unsigned int f;I int argc;  VERIFY_CONTEXT(xctx, ctx); SETARGCOUNT(argc);% if (argc < 2) return SS$_INSFARG; & if (str == 0) return SS$_BADPARAM;* if (ctx->ctx == 0) return SS$_NOLINKS; f = (argc > 2) ? flags : 0;e if (f & NET_M_NOTRM) {E return netlib_write(&ctx->ctx, str, 0, 0, (argc > 3) ? iosb : 0,@ (argc > 4) ? astadr : 0, (argc > 5) ? astprm : 0); } else {C return netlib_writeline(&ctx->ctx, str, (argc > 3) ? iosb : 0,n@ (argc > 4) ? astadr : 0, (argc > 5) ? astprm : 0); }a} /* tcp_send */ t/***++** ROUTINE: tcp_receive**** FUNCTIONAL DESCRIPTION:**%** Reads data off a TCP connection.C**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**G** TCP_RECEIVE ctxptr, bufdsc [,iosb] [,astadr] [,astprm] [,timeout]s**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.n**** COMPLETION CODES: See code.***** SIDE EFFECTS: None.****--*/Nunsigned int tcp_receive (struct COMPATCTX **xctx, struct dsc$descriptor *str,I struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm,n TIME *timeout) { struct COMPATCTX *ctx; struct dsc$descriptor dsc; unsigned int status; int argc;a VERIFY_CONTEXT(xctx, ctx); SETARGCOUNT(argc);% if (argc < 2) return SS$_INSFARG;i& if (str == 0) return SS$_BADPARAM;* if (ctx->ctx == 0) return SS$_NOLINKS;/*J** HACK to support broken MGFTP code, which passes us a static descriptor,** which is set up as a dynamic descriptor!*/K status = lib$analyze_sdesc(str, &dsc.dsc$w_length, &dsc.dsc$a_pointer);D$ dsc.dsc$b_dtype = DSC$K_DTYPE_T;$ dsc.dsc$b_class = DSC$K_CLASS_S;J return netlib_read(&ctx->ctx, &dsc, 0, 0, 0, (argc > 5) ? timeout : 0,> (argc > 2) ? iosb : 0, (argc > 3) ? astadr : 0,( (argc > 4) ? astprm : 0);} /* tcp_receive */t p/***++** ROUTINE: tcp_get_line **** FUNCTIONAL DESCRIPTION:n**G** Reads a "line" of data (a string of characters which is terminatedr3** with a CR/LF sequence) from the TCP connection. **B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**I** TCP_GET_LINE ctxptr, bufdsc [,iosb] [,astadr] [,astprm], [,timeout]E**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.t**** COMPLETION CODES: See code.M**** SIDE EFFECTS: None.****--*/Ounsigned int tcp_get_line (struct COMPATCTX **xctx, struct dsc$descriptor *str,rI struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm,s TIME *timeout) { struct COMPATCTX *ctx;2 static unsigned int flags = NETLIB_M_ALLOW_LF;( static TIME default_timeout = {1,0}; static int did_timeout = 0;e< static $DESCRIPTOR(default_timeoutdsc, "0 00:10:00.00"); int argc;= VERIFY_CONTEXT(xctx, ctx); SETARGCOUNT(argc);% if (argc < 2) return SS$_INSFARG;Y& if (str == 0) return SS$_BADPARAM;* if (ctx->ctx == 0) return SS$_NOLINKS;Z if (!did_timeout) did_timeout = OK(sys$bintim(&default_timeoutdsc, &default_timeout));5 return netlib_readline(&ctx->ctx, str, 0, &flags,lG (argc > 5 && timeout != 0) ? timeout : &default_timeout,> (argc > 2) ? iosb : 0, (argc > 3) ? astadr : 0,( (argc > 4) ? astprm : 0);} /* tcp_get_line */ T/***++** ROUTINE: udp_sendO**** FUNCTIONAL DESCRIPTION:N**** Sends a UDP datagram.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**4** UDP_SEND ctxptr, address, port, bufptr, buflen**** IMPLICIT INPUTS: None.**** IMPLICà NETLIB_SRC.BCKê ç [NETLIB]COMPATIBILITY.C;29Z?˨-IT OUTPUTS: None. **** COMPLETION CODES: See code. **** SIDE EFFECTS: None.****--*/Funsigned int udp_send (struct COMPATCTX **xctx, struct INADDRDEF addr,B unsigned short port, void *buf, unsigned short buflen) { struct COMPATCTX *ctx; struct SINDEF sin; struct dsc$descriptor dsc; VERIFY_CONTEXT(xctx, ctx);* if (ctx->ctx == 0) return SS$_NOLINKS;$ dsc.dsc$b_dtype = DSC$K_DTYPE_T;$ dsc.dsc$b_class = DSC$K_CLASS_S; dsc.dsc$w_length = buflen; dsc.dsc$a_pointer = buf;! memset(&sin, 0, sizeof(sin));e( sin.sin_w_family = NETLIB_K_AF_INET; sin.sin_x_addr = addr;, sin.sin_w_port = netlib_word_swap(port);9 return netlib_write(&ctx->ctx, &dsc, &sin, &sinsize);n} /* udp_send */ /***++** ROUTINE: udp_receive**** FUNCTIONAL DESCRIPTION:M**** Receives a UDP datagram.;**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**>** UDP_RECEIVE ctxptr, bufptr, bufsize [,retlen] [,srcaddr]@** [,srcport] [,timeout] [,iosb] [,astadr] [,astprm]**D** N.B.: for synchronous calls, srcport should be the address of aC** longword. For asynchronous calls, it should be the address2** of a word.**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None. **** COMPLETION CODES: See code.)**** SIDE EFFECTS: None.****--*/@unsigned int udp_receive (struct COMPATCTX **xctx, void *bufptr,= unsigned short bufsize, unsigned short *buflen,i? struct INADDRDEF *srcaddr, unsigned int *srcport,i8 TIME *timeout, struct NETLIBIOSBDEF *iosb,/ void (*astadr)(), void *astprm) {  struct COMPATCTX *ctx; struct SINDEF sin; struct dsc$descriptor dsc; unsigned int status; int argc;t VERIFY_CONTEXT(xctx, ctx); SETARGCOUNT(argc);% if (argc < 3) return SS$_INSFARG;) if (bufptr == 0) return SS$_BADPARAM;s* if (ctx->ctx == 0) return SS$_NOLINKS;$ dsc.dsc$b_dtype = DSC$K_DTYPE_T;$ dsc.dsc$b_class = DSC$K_CLASS_S; dsc.dsc$a_pointer = bufptr;x dsc.dsc$w_length = bufsize;" if (argc > 8 && astadr != 0) {" ctx->retaddr = srcaddr; / ctx->retport = (unsigned short *) srcport;D ctx->retlenp = buflen;u ctx->user_iosb = iosb;P ctx->astadr = astadr;+ ctx->astprm = (argc > 9) ? astprm : 0; @ return netlib_read(&ctx->ctx, &dsc, &ctx->rcvsin, &sinsize,8 &ctx->rcvsinlen, timeout, &ctx->iosb,- udp_read_completion, ctx);* }EA status = netlib_read(&ctx->ctx, &dsc, &ctx->rcvsin, &sinsize,A &ctx->rcvsinlen, (argc > 6) ? timeout : 0, &ctx->iosb);  if (OK(status)) {hC if (argc > 3 && buflen != 0) *buflen = ctx->iosb.iosb_w_count;sE if (argc > 4 && srcaddr != 0) *srcaddr = ctx->rcvsin.sin_x_addr;s" if (argc > 5 && srcport != 0)= *srcport = netlib_word_swap(ctx->rcvsin.sin_w_port);( }4K if (argc > 7 && iosb != 0) memcpy(iosb, &ctx->iosb, sizeof(ctx->iosb)); return status;} /* udp_receive */e b/***++ ** ROUTINE: udp_read_completion**** FUNCTIONAL DESCRIPTION: **G** AST completion routine for asynchronous UDP_READ calls. Does somem<** pre-processing before invoking the caller's AST routine.**** RETURNS: void **** PROTOTYPE:**** UDP_READ_COMPLETION ctx**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None. **** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/9static void udp_read_completion (struct COMPATCTX *ctx) {/*E** Stash the originating address and port, if the caller wanted themc*/& if (OK(ctx->iosb.iosb_w_status)) {E if (ctx->retaddr != 0) *(ctx->retaddr) = ctx->rcvsin.sin_x_addr;r if (ctx->retport != 0)CD *(ctx->retport) = netlib_word_swap(ctx->rcvsin.sin_w_port);E if (ctx->retlenp != 0) *(ctx->retlenp) = ctx->iosb.iosb_w_count;n }n/*$** Stash the IOSB, if it was wanted*/S if (ctx->user_iosb != 0) memcpy(ctx->user_iosb, &ctx->iosb, sizeof(ctx->iosb));X/*#** Invoke the caller's AST routiner*/ (*ctx->astadr)(ctx->astprm);} /* udp_read_completion */; /***++"** ROUTINE: net_set_trace_routine**** FUNCTIONAL DESCRIPTION:**C** This routine was used in the V1 interface for tracing activity ;** of the MX lookup routine. It no longer has any effect.e**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**"** NET_SET_TRACE_ROUTINE rtnptr**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None. **1** COMPLETION CODES: SS$_NORMAL always returned.**** SIDE EFFECTS: None.****--*/@unsigned int net_set_trace_routine (unsigned int (*routine)()) { return SS$_NORMAL;} /* net_set_trace_routine */o a/***++** ROUTINE: dns_mxlookN**** FUNCTIONAL DESCRIPTION:)**A** Looks up MX RR's in the DNS for a domain name. Returns themtE** in an array of special structures (the same structure is used for*'** the V2 equivalent of this routine). **B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**5** DNS_MXLOOK name, mxrrsize [,mxrrcount], mxrrptrE**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None._**** COMPLETION CODES: See code.;**** SIDE EFFECTS: None.****--*/Hunsigned int dns_mxlook(struct dsc$descriptor *name, unsigned int *size,? unsigned int *count, struct MXRRDEF *mxrr) {N void *ctx; unsigned int status;! status = netlib_socket(&ctx);# if (!OK(status)) return status;NA status = netlib_dns_mx_lookup(&ctx, name, mxrr, size, count);R netlib_close(&ctx);T return status;} /* dns_mxlook */ÿÿ,lclport]**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/3unsigned int net_get_info (struct COMPATCTX **xctx,> stà NETLIB_SRC.BCKë ç [NETLIB]CONNECT.C;9Owüð*[NETLIB]CONNECT.C;9+,ë ./€ 4O‚-ç 0ª123KÿPWO56ä¢múª˜7™¶múª˜8—͈çvš9¹AJ(ú›G€HˆªJÿ/***++** FACILITY: NETLIB**** ABSTRACT: Connect by name.**** MODULE DESCRIPTION:**=** This module contains the NETLIB_CONNECT_BY_NAME routine,E** which does establishes an active TCP connect to a remote host and&** port by name, rather than address.**** AUTHOR: M. MadisonM** COPYRIGHT © 1994, 1995 MADGOAT SOFTWARE. ALL RIGHTS RESERVED.**** CREATION DATE: 25-OCT-1994**** MODIFICATION HISTORY:**1** 25-OCT-1994 V1.0 Madison Initial coding.E** 17-NOV-1994 V1.0-1 Madison Don't use _both_ DNS & host tables!E** 19-JAN-1994 V1.0-2 Madison Fix connect() call completion args.**--*/#include "netlib.h"/*0** Context structure used to track our progress*/ struct Connect_Context { struct NETLIBIOSBDEF iosb; struct dsc$descriptor dsc; unsigned int ctxsize; char *name; struct CTX *ctx; int state;- unsigned int adrcnt, htadrcnt, nsadrcnt; int curadr; void (*astadr)(); void *astprm;% struct NETLIBIOSBDEF *user_iosb; struct SINDEF sin; struct INADDRDEF *adrlst;/ struct INADDRDEF htadrlst[8], nsadrlst[8]; };/*** Forward declarations*/: unsigned int netlib_connect_by_name(struct CTX **xctx,? struct dsc$descriptor *dsc, unsigned short *port,J struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm);@ static unsigned int do_connect(struct Connect_Context *con);/*** OWN storage*/5 static unsigned int usedns = NETLIB_K_LOOKUP_DNS;< static unsigned int useht = NETLIB_K_LOOKUP_HOST_TABLE;8 static unsigned int sinsize = sizeof(struct SINDEF);/*** External references*/F unsigned int netlib_name_to_address(struct CTX **, unsigned int *,: struct dsc$descriptor *, struct INADDRDEF *,# unsigned int *, ...);? unsigned int netlib_connect(struct CTX **, struct SINDEF *,# unsigned int *, ...);O unsigned int netlib_strtoaddr(struct dsc$descriptor *, struct INADDRDEF *); /***++#** ROUTINE: netlib_connect_by_name**** FUNCTIONAL DESCRIPTION:**D** Connects to a remote host/port by name. The name is looked up,D** then a connection is tried to each address until a connection is,** established, or we run out of addresses.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**M** NETLIB_CONNECT_BY_NAME ctxptr, namdsc, port [,iosb] [,astadr] [,astprm]**I** ctxptr: NETLIB context, longword (unsigned), read only, by referenceD** namdsc: char_string, character string, read only, by descriptorD** port: word_unsigned, word (unsigned), read only, by referenceK** iosb: io_status_block, quadword (unsigned), write only, by reference?** astadr: ast_procedure, procedure value, call, by reference?** astprm: user_arg, longword (unsigned), read only, by value**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES:2** SS$_NORMAL: normal successful completion*** SS$_INSFARG: not enough arguments'** SS$_BADPARAM: invalid argument2** Codes from LIB$GET_VM, LIB$ANALYZE_SDESC, and'** other NETLIB network status codes.**** SIDE EFFECTS: None.****--*/7unsigned int netlib_connect_by_name (struct CTX **xctx,? struct dsc$descriptor *dsc, unsigned short *port,K struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm) { struct Connect_Context *con; struct CTX *ctx; struct INADDRDEF addr; unsigned int status, size; unsigned short namlen; char *namp; int argc;/*** Verify the arguments*/ VERIFY_CTX(xctx, ctx); SETARGCOUNT(argc);% if (argc < 3) return SS$_INSFARG;3 if (dsc == 0 || port == 0) return SS$_BADPARAM;/*/** Allocate and fill in the connection context*/4 status = lib$analyze_sdesc(dsc, &namlen, &namp);# if (!OK(status)) return status;3 size = namlen + sizeof(struct Connect_Context);% status = lib$get_vm(&size, &con);# if (!OK(status)) return status; memset(con, 0, size);# con->name = (char *) (con + 1);$ memcpy(con->name, namp, namlen);, INIT_SDESC(con->dsc, namlen, con->name); con->ctx = ctx;- con->sin.sin_w_family = NETLIB_K_AF_INET;2 con->sin.sin_w_port = netlib_word_swap(*port); con->ctxsize = size;: size = sizeof(con->htadrlst)/sizeof(con->htadrlst[0]);5 if (argc > 3 && iosb != 0) con->user_iosb = iosb;" if (argc > 4 && astadr != 0) { con->astadr = astadr;( if (argc > 5) con->astprm = astprm; }/*>** If they provided us with a dotted-decimal IP address, fake@** out do_connect to make it look like we looked up the address ** via DNS.*/1 if (OK(netlib_strtoaddr(&con->dsc, &addr))) {* con->iosb.iosb_w_status = SS$_NORMAL; con->nsadrcnt = 1; con->nsadrlst[0] = addr;A if (con->astadr != 0) return sys$dclast(do_connect, con, 0); return do_connect(con); }/*B** Make lookup via host table synchronous and in main-line thread<** because we can't call it from AST level for all packages*/A status = netlib_name_to_address(&con->ctx, &useht, &con->dsc,@ con->htadrlst, &size, &con->htadrcnt, &con->iosb);' if (!OK(status)) con->htadrcnt = 0;: size = sizeof(con->nsadrlst)/sizeof(con->nsadrlst[0]);/*E** For an asynch call, do the DNS lookup and have DO_CONNECT invoked** as the AST routine*/" if (argc > 4 && astadr != 0) {C status = netlib_name_to_address(&con->ctx, &usedns, &con->dsc,? con->nsadrlst, &size, &con->nsadrcnt, &con->iosb, do_connect, con);7 if (!OK(status)) lib$free_vm(&con->ctxsize, &con); return status; }/**** Synchronous call: do the DNS lookup...*/B status = netlib_name_to_address(&con->ctx, &usedns, &con->dsc,@ con->nsadrlst, &size, &con->nsadrcnt, &con->iosb);/*D** ... if it failed, fall back on the host table lookup info we got*/ if (!OK(status)) {- con->iosb.iosb_w_status = SS$_ENDOFFILE; con->nsadrcnt = 0; }/*0** Just call DO_CONNECT to complete this for us*/ return do_connect(con);} /* netlib_connect_by_name */ /***++** ROUTINE: do_connect**** FUNCTIONAL DESCRIPTION:**;** Completion routine for NETLIB_CONNECT_BY_NAME. Can be@** invoked as a regular main-line routine or an AST completion.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**#** DO_CONNECT connection-context**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**5** COMPLETION CODES: Any NETLIB network status code.**** SIDE EFFECTS: None.****--*/>static unsigned int do_connect (struct Connect_Context *con) { unsigned int status; int done;/*;** We implement our FSM as a loop for the synchronous case*/ done = 0; while (!done) {& status à NETLIB_SRC.BCKë ç [NETLIB]CONNECT.C;9OF|= con->iosb.iosb_w_status; switch (con->state) {/*F** Initial state -- if the DNS lookup failed, fall back on host table4** entry. Otherwise, start trying the connections.*/ case 0:# if (con->nsadrcnt == 0) {' if (con->htadrcnt == 0) {7 con->iosb.iosb_w_status = SS$_ENDOFFILE; done = 1; break; }* con->adrlst = con->htadrlst;* con->adrcnt = con->htadrcnt; } else {* con->adrlst = con->nsadrlst;* con->adrcnt = con->nsadrcnt; } con->state = 1; /* and fall through *//*!** State 1: Attempt a connection*/ case 1:; con->sin.sin_x_addr = con->adrlst[con->curadr++]; con->state = 2;A status = netlib_connect(&con->ctx, &con->sin, &sinsize,C &con->iosb, (con->astadr == 0) ? 0 : do_connect,7 (con->astadr == 0) ? 0 : con);$ if (!OK(status)) done = 1;, else if (con->astadr != 0) return; break;/*D** State 2: connect() completion status check. If we're successfulB** or we've run out of addresses, we're done. Otherwise, we loop** back up and try again.*/ case 2:A if (OK(status) || con->curadr >= con->adrcnt) done = 1; con->state = 1; break; } }/*B** We're done, one way or another. Fill in the caller's IOSB and(** call back the AST, if there was one.*/ if (con->user_iosb != 0); memcpy(con->user_iosb, &con->iosb, sizeof(con->iosb));6 if (con->astadr != 0) (*con->astadr)(con->astprm);/*+** We're done with this context -- free it*/% lib$free_vm(&con->ctxsize, &con);/*'** Synchronous completion occurs here.*/ return status;} /* do_connect */ÿÿà  NETLIB_SRC.BCKí ç [NETLIB]DNS.C;20Z´îà*[NETLIB]DNS.C;20+,í ./€ 4ZÜ-ç 0ª123KÿPWO56uÊË ›70ò Ë ›89¹AJ(ú›G€HˆªJÿ/***++** FACILITY: NETLIB**#** ABSTRACT: DNS resolver support.**** MODULE DESCRIPTION:**D** This module contains support routines for implementing NETLIB's!** Domain Name Service resolver.**** AUTHOR: M. Madison7** COPYRIGHT © 1994, 1996 MADGOAT SOFTWARE."** ALL RIGHTS RESERVED.**** CREATION DATE: 22-OCT-1994**** MODIFICATION HISTORY:**1** 22-OCT-1994 V1.0 Madison Initial coding.B** 17-NOV-1994 V1.1 Madison Removed socket from DNS context.2** 18-NOV-1994 V1.2 Madison Add retry count.H** 12-FEB-1996 V1.2-1 Madison Fixed rather stupid bug in expandname.Z** 04-MAR-1997 V1.2-2 Madison Fixed stupid bug in dns_init (counter/ptr update order).**--*/#include "netlib.h"#include /*** Forward declarations*/4 unsigned int netlib___dns_init(struct CTX *ctx);4 void netlib___free_dns_context(struct CTX *ctx);I int netlib_dns_skipname(unsigned char *bufp, unsigned short *buflen);R unsigned int netlib_dns_expandname(unsigned char *buf, unsigned short *buflen,A unsigned char *bufp, struct dsc$descriptor *namdsc,? unsigned short *retlen, unsigned short *bufchrs);/*** OWN storage*/6 static $DESCRIPTOR(default_timeout, "0 00:00:05");/*** External references*/- int netlib___get_nameservers(QUEUE *nsq);F int netlib___get_domain(char *, unsigned short, unsigned short *); /***++** ROUTINE: netlib___dns_init**** FUNCTIONAL DESCRIPTION:**2** Initializes an internal DNS resolver context.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**'** netlib___dns_init(struct CTX *ctx)**1** ctx: NETLIB context, modify, by reference.**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/2unsigned int netlib___dns_init (struct CTX *ctx) { struct DOMAIN *dom; unsigned int status; ITMLST lnmlst[3]; int i, maxidx; unsigned int size; unsigned short buflen; char buf[256];7 static unsigned int socktype = NETLIB_K_TYPE_DGRAM;8 static unsigned int ctxsize = sizeof(struct DNSCTX);/ static $DESCRIPTOR(tabnam, "LNM$FILE_DEV");7 static $DESCRIPTOR(lognam, "NETLIB_SEARCH_DOMAIN");/*%** Allocate the DNS resolver context*/0 status = lib$get_vm(&ctxsize, &ctx->dnsctx);# if (!OK(status)) return status;! INIT_QUEUE(ctx->dnsctx->nsq);" INIT_QUEUE(ctx->dnsctx->domq);/*:** Get the list of name servers we're supposed to contact*/; if (netlib___get_nameservers(&ctx->dnsctx->nsq) == 0) {) lib$free_vm(&ctxsize, &ctx->dnsctx); ctx->dnsctx = 0; ctx->flags |= CTX_M_NO_DNS; return SS$_UNSUPPORTED; }/*B** Get the list of NETLIB search domains, or the package-specific ** ones.*/G ITMLST_INIT(lnmlst[0], LNM$_MAX_INDEX, sizeof(maxidx), &maxidx, 0);' ITMLST_INIT(lnmlst[1], 0, 0, 0, 0);9 if (OK(sys$trnlnm(0, &tabnam, &lognam, 0, lnmlst))) {: ITMLST_INIT(lnmlst[0], LNM$_INDEX, sizeof(i), &i, 0);D ITMLST_INIT(lnmlst[1], LNM$_STRING, sizeof(buf), buf, &buflen);( ITMLST_INIT(lnmlst[2], 0, 0, 0, 0);$ for (i = 0; i <= maxidx; i++) {M if (OK(sys$trnlnm(0, &tabnam, &lognam, 0, lnmlst)) && buflen != 0) {0 size = buflen + sizeof(struct DOMAIN);, if (OK(lib$get_vm(&size, &dom))) {# dom->length = buflen;- memcpy(dom->name, buf, buflen);' dom->name[buflen] = '\0';8 queue_insert(dom, ctx->dnsctx->domq.tail); } } }@ } else if (netlib___get_domain(buf, sizeof(buf), &buflen)) { char *cp, *cp1; int remain; cp = buf; remain = buflen;/*I** A search domain must have at least two parts, to avoid the ".com.edu"I** problem, which is why we check to make sure that the remaining domain ** string has at least one dot.*/ while (remain > 0) {' cp1 = memchr(cp, '.', remain); if (cp1 == 0) break;/ size = remain + sizeof(struct DOMAIN);+ if (OK(lib$get_vm(&size, &dom))) { dom->length = remain;( memcpy(dom->name, cp, remain);# dom->name[remain] = '\0';4 queue_insert(dom, ctx->dnsctx->domq.tail); }" remain -= (cp1 - cp) + 1; cp = cp1 + 1; } }8 sys$bintim(&default_timeout, &ctx->dnsctx->timeout);! ctx->dnsctx->retry_count = 4; return SS$_NORMAL;} /* netlib___dns_init */  /***++&** ROUTINE: netlib___free_dns_context**** FUNCTIONAL DESCRIPTION:**&** Deallocates the resolver context.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**/** netlib___free_dns_context(struct CTX *ctx)**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/2void netlib___free_dns_context (struct CTX *ctx) { struct NAMESERVER *ns; struct DOMAIN *d; unsigned int size;! if (ctx->dnsctx == 0) return;% size = sizeof(struct NAMESERVER);M while (queue_remove(ctx->dnsctx->nsq.head, &ns)) lib$free_vm(&size, &ns);6 while (queue_remove(ctx->dnsctx->domq.head, &d)) {. size = sizeof(struct DOMAIN) + d->length; lib$free_vm(&size, &d); }! size = sizeof(struct DNSCTX);% lib$free_vm(&size, &ctx->dnsctx); ctx->dnsctx = 0;!} /* netlib___free_dns_context */ /***++ ** ROUTINE: netlib_dns_skipname**** FUNCTIONAL DESCRIPTION:**@** Utility routine for skipping over a name in a DNS response.F** Handles the compressed form of domain string that DNS packets use.**** RETURNS: longword_signed**E** The number of bytes to be skipped in the DNS packet is returned.**** PROTOTYPE:**&** NETLIB_DNS_SKIPNAME bufp, buflen**B** bufp: char_string, character string, read only, by referenceC** buflen: word_unsigned, word (unsigned), read only, by reference**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/Gint netlib_dns_skipname (unsigned char *bufp, unsigned short *buflen) { unsigned char *cp, *eom; cp = bufp; eom = cp + *buflen;" while (cp < eom && *cp != 0) { if (*cp >= 64) cp++; else cp += *cp + 1; } return (cp - bufp) + 1;} /* netlib_dns_skipname */ /***++"** ROUTINE: netlib_dns_expandname**** FUNCTIONAL DESCRIPTION:**C** Expands a domain string from a DNS reply packet into somethingE** human-readable. The string is returned, along with the number ofK** bytes in the DNS packet that composed the name (which won't necessarilyG** be the same as the string length because of the compression used in** DNS packets).**>** RETURNS: cond_value, condition value, write only, by value**** PROTOTYPE:**H** NETLIB_DNS_EXPANDNAME buf, buflen, bufp, namdsc [,retlen] [,count]**C** buf: char_string, character string, read only, by referenceD** buflen: word_unsigned, word (unsigned), read only, by reference?** bufp: pointer, longword (unsigned), modify, by referenceE** namdsc: char_string, character string, write only, by descriptorE** retlen: word_unsigned, word (unsigned), write only, by referenceE** count: word_unsigned, word (unsigned),  NETLIB_SRC.BCKí ç [NETLIB]DNS.C;20Z write only, by reference**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/Ounsigned int netlib_dns_expandname (unsigned char *buf, unsigned short *buflen,= unsigned char *bufp, struct dsc$descriptor *namdsc,; unsigned short *retlen, unsigned short *countp) { int argc, indirect; struct dsc$descriptor dsc; char name[256], *namp;! unsigned short namlen, count; unsigned int status; SETARGCOUNT(argc); namp = name; indirect = 0; count = 0; while (*bufp != 0) { if (*bufp < 64) {+ if (!indirect) count += *bufp + 1;. if (namp-name+*bufp < sizeof(name)) {& memcpy(namp, bufp+1, *bufp); namp += *bufp; *namp++ = '.'; } bufp += *bufp + 1; } else {# if (!indirect) count += 2; indirect = 1;K bufp = buf + (netlib_word_swap(*(unsigned short *)bufp) - 0xc000);7 if (bufp - buf > *buflen) return SS$_BADPARAM; } }G if (!indirect) count += 1; /* for the extra null byte at the end */) INIT_SDESC(dsc, (namp-name)-1, name);* status = lib$scopy_dxdx(&dsc, namdsc);# if (!OK(status)) return status;; if (argc > 4 && retlen != 0) *retlen = namp - name - 1;1 if (argc > 5 && countp != 0) *countp = count; return SS$_NORMAL;} /* netlib_dns_expandname */ÿÿà  NETLIB_SRC.BCKî ç [NETLIB]DNS_MXLOOK.C;8[¼ ð*[NETLIB]DNS_MXLOOK.C;8+,î ./€ 4[À-ç 0ª123KÿPWO56° yM‰„˜7ðâˆM‰„˜86Àçvš9¹AJ(ú›G€HˆªJÿ/***++** FACILITY: NETLIB**'** ABSTRACT: DNS MX RR lookup routines**** MODULE DESCRIPTION:**?** This module contains routines for implementing MX resource6** record lookups in the DNS using NETLIB's resolver.**** AUTHOR: M. MadisonG** COPYRIGHT © 1994, MADGOAT SOFTWARE. ALL RIGHTS RESERVED.**** CREATION DATE: 25-OCT-1994**** MODIFICATION HISTORY:**1** 25-OCT-1994 V1.0 Madison Initial coding.**--*/#include "netlib.h"/*** Forward declarations*/: unsigned int netlib___dns_mx_lookup(struct CTX **xctx,B struct dsc$descriptor *namdsc, struct MXRRDEF *mxrr,> unsigned int *mxrrsize, unsigned int *mxrrcount,J struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm);A static unsigned int mxlook_completion(struct DNSREQ *dnsreq);/*** External references*/4 unsigned int netlib___dns_init(struct CTX *ctx);S unsigned int netlib_dns_query(struct CTX **xctx, struct dsc$descriptor *namdsc,6 unsigned int *class, unsigned int *type,: unsigned char *buf, unsigned short *bufsize,> unsigned int *flags, struct NETLIBIOSBDEF *iosb,. void (*astadr)(), void *astprm);I int netlib_dns_skipname(unsigned char *bufp, unsigned short *buflen);R unsigned int netlib_dns_expandname(unsigned char *buf, unsigned short *buflen,A unsigned char *bufp, struct dsc$descriptor *namdsc,? unsigned short *retlen, unsigned short *bufchrs); /***++#** ROUTINE: netlib___dns_mx_lookup**** FUNCTIONAL DESCRIPTION:**?** Performs an MX RR lookup, returning the information in the** special MXRRDEF structure.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**E** NETLIB___DNS_MX_LOOKUP ctx, namdsc, mxrr, mxrrsize [,mxrrcount]4** [,iosb] [,astadr] [,astprm]**Q** ctx: NETLIB context address, longword (unsigned), read only, by referenceD** namdsc: char_string, character string, read only, by descriptorM** mxrr: MXRRDEF structure, longword (unsigned), write only, by referenceM** mxrrsize: longword_unsigned, longword (unsigned), read only, by referenceO** mxrrcount: longword_unsigned, longword (unsigned), write only, by referenceL** iosb: I/O status block, quadword (unsigned), write only, by reference>** astadr: ast_procedure, procedure mask, call, by reference?** astprm: user_arg, longword (unsigned), read only, by value**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES:****** SIDE EFFECTS: None.****--*/6unsigned int netlib___dns_mx_lookup(struct CTX **xctx,B struct dsc$descriptor *namdsc, struct MXRRDEF *mxrr,> unsigned int *mxrrsize, unsigned int *mxrrcount,K struct NETLIBIOSBDEF *iosb, void (*astadr)(), void *astprm) { struct CTX *ctx; struct DNSREQ *dnsreq; struct IOR *ior; unsigned short bufsize; unsigned int status; int argc;6 static unsigned int class = NETLIB_K_DNS_CLASS_IN;5 static unsigned int type = NETLIB_K_DNS_TYPE_MX;< static unsigned int queryflags = NETLIB_M_DOMAIN_SEARCH; VERIFY_CTX(xctx, ctx); SETARGCOUNT(argc);/*** Check arguments*/% if (argc < 4) return SS$_INSFARG;G if (namdsc == 0 || mxrr == 0 || mxrrsize == 0) return SS$_BADPARAM;/*C** If NETLIB___DNS_INIT couldn't initialize the resolver, we don't** do DNS stuff*/: if (ctx->flags & CTX_M_NO_DNS) return SS$_UNSUPPORTED;/*)** Initialize the resolver, if necessary*/ if (ctx->dnsctx == 0) {% status = netlib___dns_init(ctx);- if (!OK(status)) return SS$_UNSUPPORTED; }/*K** Allocate a DNS request block (also gets us a generic I/O request block)*/2 GET_DNSREQ(dnsreq, ctx, (argc > 5) ? iosb : 0,+ (argc > 6) ? astadr : 0,, (argc > 7) ? astprm : 0);/*+** Fill in the request and start the query*/ ior = dnsreq->ior; ior->arg[0].address = mxrr;% ior->arg[1].longword = *mxrrsize;5 ior->arg[2].address = (argc > 4) ? mxrrcount : 0;" bufsize = sizeof(dnsreq->buf);: status = netlib_dns_query(&ctx, namdsc, &class, &type,% dnsreq->buf, &bufsize, &queryflags, &ior->iosb,& (ior->astadr == 0) ? 0 = : (void (*)()) mxlook_completion, dnsreq);( if (ior->astadr != 0) return status; if (!OK(status)) { FREE_DNSREQ(dnsreq); return status; }/*>** We get to this point if the query completed synchronously.*/% return mxlook_completion(dnsreq);} /* netlib___dns_mx_lookup */ /***++** ROUTINE: mxlook_completion**** FUNCTIONAL DESCRIPTION:**>** Completion routine for NETLIB___DNS_MXLOOKUP. Can eitherA** be called as an AST routine or in the main-line thread if the&** DNS query completed synchronously.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**"** MXLOOK_COMPLETION dnsrequest**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/?static unsigned int mxlook_completion (struct DNSREQ *dnsreq) {" struct IOR *ior = dnsreq->ior;/ struct MXRRDEF *mxrr = ior->arg[0].address;. unsigned int *count = ior->arg[2].address;$ struct dsc$descriptor dsc, dsc2;" struct NETLIB_DNS_HEADER *hdr; unsigned char *cp; char name[256];0 unsigned short retlen, remain, buflen, skip;, int i, n, ancount, qdcount, type, class;/*&** Check the completion status first.*/' if (!OK(ior->iosb.iosb_w_status)) { if (ior->iosbp != 0) {= ior->iosbp->iosb_w_status = ior->iosb.iosb_w_status;' ior->iosbp->iosb_w_count = 0;' ior->iosbp->iosb_l_unused = 0; } if (count != 0) *count = 0;7 if (ior->astadr != 0) (*ior->astadr)(ior->astprm); FREE_DNSREQ(dnsreq);$ return ior->iosb.iosb_w_status; }/*7** Status was OK, so let's parse out the reply packet.*/3 hdr = (struct NETLIB_DNS_HEADER *) dnsreq->buf;3 ancount = netlib_word_swap(hdr->dns_w_ancount);3 qdcount = netlib_word_swap(hdr->dns_w_qdcount);/*N** We treat all failures as "end of file" (no such name or domain) responses.*/; if (hdr->dns_v_reply_code != NETLIB_K_DNS_RC_SUCCESS) {/ ior->iosbp->iosb_w_status = SS$_ENDOFFILE;" ior->iosbp->iosb_w_count = 0;# ior->iosbp->iosb_l_unused = 0; if (count != 0) *count = 0;7 if (ior->astadr != 0) (*ior->astadr)(ior->astprm); FREE_DNSREQ(dnsreq); return SS$_ENDOFFILE; }/*** Skip over the question*/$ buflen = ior->iosb.iosb_w_count;$ remain = buflen - sizeof(*hdr);$ cp = dnsreq->buf + sizeof(*hdr); while (qdcount-- > 0) {. i = netlib_dns_skipname(cp, &remain) + 4; cà  NETLIB_SRC.BCKî ç [NETLIB]DNS_MXLOOK.C;8[j,p += i; remain -= i; }/*6** Now parse out the answers, looking for the MX RRs.*/( INIT_SDESC(dsc, sizeof(name), name); n = 0;E while (ancount-- > 0 && remain > 0 && n < ior->arg[1].longword) {[ if (!OK(netlib_dns_expandname(dnsreq->buf, &buflen, cp, &dsc, &retlen, &skip))) break; cp += skip; remain -= skip;4 type = netlib_word_swap(*(unsigned short *)cp); cp += 2; remain -= 2;5 class = netlib_word_swap(*(unsigned short *)cp);3 cp += 6; remain -= 6; /* skip over TTL, too */1 i = netlib_word_swap(*(unsigned short *)cp); cp += 2; remain -= 2;( if (type == NETLIB_K_DNS_TYPE_MX) {M mxrr[n].mxrr_l_preference = netlib_word_swap(*(unsigned short *)cp);C INIT_SDESC(dsc2, NETLIB_S_MXRR_NAME, mxrr[n].mxrr_t_name);T netlib_dns_expandname(dnsreq->buf, &buflen, cp + 2, &dsc2, &retlen, &skip);( mxrr[n].mxrr_l_length = retlen; n++; } cp += i; remain -= i; }/*D** Fill in the status and RR count information and either call back)** (for an AST) or return to the caller.*/ if (count != 0) *count = n; if (ior->iosbp != 0) {, ior->iosbp->iosb_w_status = SS$_NORMAL;# ior->iosbp->iosb_w_count = n;# ior->iosbp->iosb_l_unused = 0; }1 if (ior->astadr) (*ior->astadr)(ior->astprm); FREE_DNSREQ(dnsreq); return SS$_NORMAL;} /* mxlook_completion */ÿÿà  NETLIB_SRC.BCKï ç [NETLIB]DNS_QUERY.C;23Y1sð*[NETLIB]DNS_QUERY.C;23+,ï .1/€ 4Y1%&-ç 0ª123KÿPWO&56𓼌„˜7Pô©¼Œ„˜8°Ñçvš9¹AJ(ú›G€HˆªJÿ/***++** FACILITY: NETLIB**E** ABSTRACT: Formulates and sends DNS queries, preprocesses replies.**** MODULE DESCRIPTION:**6** This module is the core of NETLIB's DNS resolver.**** AUTHOR: M. MadisonG** COPYRIGHT © 1994, MADGOAT SOFTWARE. ALL RIGHTS RESERVED.**** CREATION DATE: 24-OCT-1994**** MODIFICATION HISTORY:**1** 24-OCT-1994 V1.0 Madison Initial coding.8** 17-NOV-1994 V1.1 Madison Connect to nameserver.=** 18-NOV-1994 V1.2 Madison Restructure asynch queries.**--*/#include "netlib.h"/*** Forward routines*/S unsigned int netlib_dns_query(struct CTX **xctx, struct dsc$descriptor *namdsc,6 unsigned int *class, unsigned int *type,: unsigned char *buf, unsigned short *bufsize,> unsigned int *flags, struct NETLIBIOSBDEF *iosb,. void (*astadr)(), void *astprm);8 static unsigned int do_query(struct DNSREQ *dnsreq);@ static unsigned int query_nameserver(struct DNSREQ *dnsreq);8 static void query_completion(struct DNSREQ *dnsreq);0 static void do_write(struct DNSREQ *dnsreq);/ static void do_read(struct DNSREQ *dnsreq);/*** External references*/4 unsigned int netlib___dns_init(struct CTX *ctx);3 unsigned int netlib_socket(struct CTX **, ...);K unsigned int netlib_connect(struct CTX **, void *, unsigned int *,...);K unsigned int netlib_write(struct CTX **, struct dsc$descriptor *, ...);J unsigned int netlib_read(struct CTX **, struct dsc$descriptor *, ...);- unsigned int netlib_close(struct CTX **); /***++** ROUTINE: netlib_dns_query**** FUNCTIONAL DESCRIPTION:**B** Formulates a DNS query, sends it out, and obtains a reply (if** possible).**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**?** NETLIB_DNS_QUERY ctx, namdsc, [class], type, buf, bufsize8** [,flags] [,iosb] [,astadr] [,astprm]**O** ctx: NETLIB context address, longword_unsigned, read only, by referenceD** namdsc: char_string, character string, read only, by descriptorL** class: longword_unsigned, longword (unsigned), read only, by referenceL** type: longword_unsigned, longword (unsigned), read only, by referenceG** buf: varying_arg, longword (unsigned), write only, by referenceD** bufsize: word_unsigned, word (unsigned), read only, by referenceH** flags: mask_longword, longword (unsigned), read only, by referenceK** iosb: io_status_block, quadword (unsigned), write only, by reference?** astadr: ast_procedure, procedure value, call, by reference?** astprm: user_arg, longword (unsigned), read only, by value**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/Ounsigned int netlib_dns_query(struct CTX **xctx, struct dsc$descriptor *namdsc,7 unsigned int *xclass, unsigned int *type,: unsigned char *buf, unsigned short *bufsize,? unsigned int *xflags, struct NETLIBIOSBDEF *iosb,/ void (*astadr)(), void *astprm) { struct CTX *ctx; struct DNSREQ *dnsreq; struct IOR *ior;! struct NETLIB_DNS_HEADER *hp;& unsigned int class, flags, status; unsigned short namlen; char *name; int argc;/*"** Sanity-check the argument list*/ VERIFY_CTX(xctx, ctx); SETARGCOUNT(argc);% if (argc < 6) return SS$_INSFARG;R if (namdsc == 0 || type == 0 || buf == 0 || bufsize == 0) return SS$_BADPARAM;/*B** Make sure we're doing DNS, and initialize the resolver context ** if needed*/: if (ctx->flags & CTX_M_NO_DNS) return SS$_UNSUPPORTED; if (ctx->dnsctx == 0) {% status = netlib___dns_init(ctx);- if (!OK(status)) return SS$_UNSUPPORTED; }/*** Process the input arguments*/7 status = lib$analyze_sdesc(namdsc, &namlen, &name);# if (!OK(status)) return status;3 if (xclass == 0) class = NETLIB_K_DNS_CLASS_IN; else class = *xclass;@ if (argc < 7 || xflags == 0) flags = NETLIB_M_DOMAIN_SEARCH; else flags = *xflags;/*%** Allocate DNS & I/O request blocks*/2 GET_DNSREQ(dnsreq, ctx, (argc > 7) ? iosb : 0,+ (argc > 8) ? astadr : 0,, (argc > 9) ? astprm : 0);/*&** Initialize the domain search stuff*/M if ((flags & NETLIB_M_DOMAIN_SEARCH) && memchr(name, '.', namlen) == 0) {- dnsreq->curdom = ctx->dnsctx->domq.head; } else { dnsreq->curdom = 0; }/*B** Fill in the DNS request block and call DO_QUERY to do the work*/ dnsreq->query_name = name;# dnsreq->query_namlen = namlen; dnsreq->query_flags = flags; dnsreq->query_rbuf = buf;& dnsreq->query_rbufsize = *bufsize; dnsreq->query_class = class; dnsreq->query_type = *type; dnsreq->ctx = ctx;3 dnsreq->retries = ctx->dnsctx->retry_count; return do_query(dnsreq);} /* netlib_dns_query */ /***++** ROUTINE: do_query**** FUNCTIONAL DESCRIPTION:**K** Does the actual work of formatting a query. Calls on QUERY_NAMESERVER,** to send the query out and get the reply.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**** DO_QUERY dnsrequest**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/6static unsigned int do_query (struct DNSREQ *dnsreq) {" struct IOR *ior = dnsreq->ior;" struct CTX *ctx = dnsreq->ctx;$ struct DNSCTX *dc = ctx->dnsctx;! struct NETLIB_DNS_HEADER *hp; char *anchor, *cp; unsigned char *bp; int i, j; unsigned int status;/*G** This is set up as a loop for synchronous queries. For asynchronous>** queries, we return as soon as the query has been sent out.*/ while (1) {/*** Format the query header*/3 hp = (struct NETLIB_DNS_HEADER *) dnsreq->buf;5 memset(hp, 0, sizeof(struct NETLIB_DNS_HEADER));' hp->dns_w_queryid = ++dc->queryid;. hp->dns_v_opcode = NETLIB_K_DNS_OP_STDQ;Y hp->dns_v_recursion_desired = (dnsreq->query_flags & NETLIB_M_NO_RECURSION) ? 0 : 1;- hp->dns_w_qdcount = netlib_word_swap(1);/*/** Fill in the question -- the name part first*/9 bp = dnsreq->buf + sizeof(struct NETLIB_DNS_HEADER);! anchor = dnsreq->query_name; i = dnsreq->query_namlen; while (i > 0) {% cp = memchr(anchor, '.', i); if (cp == 0) { *bp++ = i;) memcpy(bp, anchor, i); bp += i; break; } else { j = cp - anchor; *bp++ = j; memcpy(bp, anchor, j); bp += j; i -= j + 1; } anchor = cp + 1; }/*9** And the search domain, if we're doing search domains.*/ if (dnsreq->curdom == 0) {J dnsreq->curdom = (dnsreq-à NETLIB_SRC.BCKï ç [NETLIB]DNS_QUERY.C;23Y1«™>query_flags & NETLIB_M_DOMAIN_SEARCH) ?? dc->domq.head : (struct DOMAIN *) &dc->domq; } else {' anchor = dnsreq->curdom->name;$ i = dnsreq->curdom->length;( if (i >= 1 && *anchor == '.') { anchor++; i--; } while (i > 0) {& cp = memchr(anchor, '.', i); if (cp == 0) { *bp++ = i;- memcpy(bp, anchor, i); bp += i; break; } else { j = cp - anchor; *bp++ = j;$ memcpy(bp, anchor, j); bp += j; i -= j + 1; } anchor = cp + 1; }0 dnsreq->curdom = dnsreq->curdom->flink; }/*1** Terminate the name, insert the type and class*/ *bp++ = '\0';L *(unsigned short *) bp = netlib_word_swap(dnsreq->query_type); bp += 2;M *(unsigned short *) bp = netlib_word_swap(dnsreq->query_class); bp += 2;' dnsreq->buflen = bp - dnsreq->buf;/*$** Start with the first name server*/" dnsreq->curns = dc->nsq.head;/*(** If ASTADR is 0, this is synchronous.*/ if (ior->astadr == 0) {/*G** Loop through all the nameservers until we get a successful response'** back, or we run out of nameservers.*/B while (dnsreq->curns != (struct NAMESERVER *) &dc->nsq) {, status = query_nameserver(dnsreq); if (OK(status)) break;/ dnsreq->curns = dnsreq->curns->flink; }/*D** Check status and verify the reply code from the server. If it'sG** not a successful reply, move on to the next search domain; if we'veF** run through all the search domains, return the ENDOFFILE error (no** such host or domain).*/ if (!OK(status)) {# status = SS$_UNREACHABLE;J } else if (dnsreq->replylen > sizeof(struct NETLIB_DNS_HEADER)) {? hp = (struct NETLIB_DNS_HEADER *) dnsreq->query_rbuf;@ if (hp->dns_v_reply_code == NETLIB_K_DNS_RC_SUCCESS) {" status = SS$_NORMAL; } else {B if (dnsreq->curdom != (struct DOMAIN *) &dc->domq) {< continue; /* back to top of while(1) loop */ }% status = SS$_ENDOFFILE; }& } else status = SS$_PROTOCOL;/*D** Return the results to the caller (still in synch I/O processing)*/ if (ior->iosbp != 0) {- ior->iosbp->iosb_w_status = status;6 ior->iosbp->iosb_w_count = dnsreq->replylen;( ior->iosbp->iosb_l_unused = 0; } FREE_DNSREQ(dnsreq); return status;/*D** For asynchronous calls, just fire off a query and do the rest of1** the processing in the AST completion routine.*/ } else {) return query_nameserver(dnsreq); } } /* while (1) */7 return SS$_DATACHECK; /* should never reach here */} /* do_query */ /***++** ROUTINE: query_nameserver**** FUNCTIONAL DESCRIPTION:**$** Sends a query to a name server.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**!** QUERY_NAMESERVER dnsrequest**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/>static unsigned int query_nameserver (struct DNSREQ *dnsreq) {" struct IOR *ior = dnsreq->ior;" struct CTX *ctx = dnsreq->ctx;, struct DNSCTX *dc = dnsreq->ctx->dnsctx;( struct NETLIB_DNS_HEADER *hp1, *hp2; struct dsc$descriptor dsc;! unsigned int status, sinsize;4 static unsigned int dgram = NETLIB_K_TYPE_DGRAM;/*** Set up the socket address*/1 memset(&dnsreq->sin, 0, sizeof(dnsreq->sin));0 dnsreq->sin.sin_w_family = NETLIB_K_AF_INET;2 dnsreq->sin.sin_w_port = netlib_word_swap(53);1 dnsreq->sin.sin_x_addr = dnsreq->curns->addr;/*A** Create the socket and "connect" it to the server. We do thisH** so we can find out right away whether or not the server is listeningE** on that UDP port, rather than waiting for the reply timeout if weJ** were to use sendto/recvfrom. It's also more efficient to do a connect(** in BSD-based TCP/IP implementations.*/H status = ior->iosb.iosb_w_status = netlib_socket(&ior->ctx, &dgram); if (OK(status)) {# sinsize = sizeof(dnsreq->sin); if (ior->astadr != 0) {C status = netlib_connect(&ior->ctx, &dnsreq->sin, &sinsize,6 &ior->iosb, do_write, dnsreq);' if (OK(status)) return status;* ior->iosb.iosb_w_status = status; } else {D status = netlib_connect(&ior->ctx, &dnsreq->sin, &sinsize); if (OK(status)) {7 INIT_SDESC(dsc, dnsreq->buflen, dnsreq->buf);C status = netlib_write(&ior->ctx, &dsc, 0, 0, &ior->iosb);; if (OK(status)) status = ior->iosb.iosb_w_status;0 else ior->iosb.iosb_w_status = status; } }. if (!OK(status)) netlib_close(&ior->ctx); } if (!OK(status)) { ior->ctx = 0;) if (ior->astadr == 0) return status; query_completion(dnsreq); return SS$_NORMAL; }/*G** OK, we've got ourselves connected and sent off the query. Now readL** the reply. This loop handles synchronous reads; asynch reply processing#** is handled in QUERY_COMPLETION.*/ while (1) {A INIT_SDESC(dsc, dnsreq->query_rbufsize, dnsreq->query_rbuf);N status = netlib_read(&ior->ctx, &dsc, 0, 0, 0, &dc->timeout, &ior->iosb);/*8** Make sure that the reply is to the query we sent out*/ if (OK(status)) {G if (ior->iosb.iosb_w_count < sizeof(struct NETLIB_DNS_HEADER)) continue;8 hp1 = (struct NETLIB_DNS_HEADER *) dnsreq->buf;? hp2 = (struct NETLIB_DNS_HEADER *) dnsreq->query_rbuf;8 if (hp1->dns_w_queryid == hp2->dns_w_queryid) {4 dnsreq->replylen = ior->iosb.iosb_w_count;" netlib_close(&ior->ctx); ior->ctx = 0; return SS$_NORMAL; }/*?** If the reply timed out, try again. This is UDP, after all.*/ } else {B if ((status == SS$_TIMEOUT) && (--dnsreq->retries > 0)) {7 INIT_SDESC(dsc, dnsreq->buflen, dnsreq->buf);C status = netlib_write(&ior->ctx, &dsc, 0, 0, &ior->iosb);# if (OK(status)) continue; }! netlib_close(&ior->ctx); ior->ctx = 0; return status; } }7 return SS$_DATACHECK; /* should never reach here */} /* query_nameserver */ /***++** ROUTINE: query_completion**** FUNCTIONAL DESCRIPTION:**2** Completion processing for a reply to a query.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**!** QUERY_COMPLETION dnsrequest**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/6static void query_completion (struct DNSREQ *dnsreq) {" struct IOR *ior = dnsreq->ior;" struct CTX *ctx = dnsreq->ctx;$ struct DNSCTX *dc = ctx->dnsctx;( struct NETLIB_DNS_HEADER *hp1, *hp2; struct dsc$descriptor dsc; unsigned int status;/*I** If completion status was OK, verify that the response is to the query5** we sent out. If it wasn't queue up another read.*/% status = ior->iosb.iosb_w_status;S if (OK(status) && ior->iosb.iosb_w_count >= sizeof(struct NETLIB_DNS_Hà NETLIB_SRC.BCKï ç [NETLIB]DNS_QUERY.C;23Y16EADER)) {4 hp1 = (struct NETLIB_DNS_HEADER *) dnsreq->buf;; hp2 = (struct NETLIB_DNS_HEADER *) dnsreq->query_rbuf;4 if (hp1->dns_w_queryid == hp2->dns_w_queryid) {4 if (ior->ctx != 0) netlib_close(&ior->ctx); ior->ctx = 0; if (ior->iosbp != 0)< memcpy(ior->iosbp, &ior->iosb, sizeof(ior->iosb));% (*ior->astadr)(ior->astprm); FREE_DNSREQ(dnsreq); return; } else {E INIT_SDESC(dsc, dnsreq->query_rbufsize, dnsreq->query_rbuf);E status = netlib_read(&ior->ctx, &dsc, 0, 0, 0, &dc->timeout,9 &ior->iosb, query_completion, dnsreq); if (OK(status)) return; } }/*'** If we timed out, re-send the query.*/= if ((status == SS$_TIMEOUT) && (--dnsreq->retries > 0)) {2 INIT_SDESC(dsc, dnsreq->buflen, dnsreq->buf);1 status = netlib_write(&ior->ctx, &dsc, 0, 0,1 &ior->iosb, do_read, dnsreq); if (OK(status)) return; }/*?** Done with this connection. Don't need the socket any more.*/ if (ior->ctx != 0) { netlib_close(&ior->ctx); ior->ctx = 0; }/*@** Set things up for moving on to next server; if we've run outC** of servers, move on to next search domain. If we've run out of9** those, we report the last error we got to the caller.*/) dnsreq->curns = dnsreq->curns->flink;: if (dnsreq->curns == (struct NAMESERVER *) &dc->nsq) {9 if (dnsreq->curdom == (struct DOMAIN *) &dc->domq) {I if (ior->iosbp != 0) < memcpy(ior->iosbp, &ior->iosb, sizeof(ior->iosb));% (*ior->astadr)(ior->astprm);  FREE_DNSREQ(dnsreq);D return; }/*** Next query*/ do_query(dnsreq); return; }E/*** Next nameserver**/ query_nameserver(dnsreq);} /* query_completion */ /***++** ROUTINE: do_writes**** FUNCTIONAL DESCRIPTION:-**B** Queue a write to the nameserver (for asynch queries). Called%** as completion AST on the connect.***B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**** DO_WRITE dnsreqc**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.s**** COMPLETION CODES: See code.n**** SIDE EFFECTS: None.****--*/.static void do_write (struct DNSREQ *dnsreq) {" struct IOR *ior = dnsreq->ior; struct dsc$descriptor dsc; unsigned int status;% status = ior->iosb.iosb_w_status;n if (OK(status)) {c2 INIT_SDESC(dsc, dnsreq->buflen, dnsreq->buf);O status = netlib_write(&ior->ctx, &dsc, 0, 0, &ior->iosb, do_read, dnsreq);t }i if (OK(status)) return;)% ior->iosb.iosb_w_status = status;  query_completion(dnsreq);s} /* do_write */ n/***++** ROUTINE: do_read**** FUNCTIONAL DESCRIPTION:n**B** Queues a read to the nameserver (for asynch queries). Called"** as completion AST to DO_WRITE.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**** DO_READ dnsrequest**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None._**** COMPLETION CODES: See code.P**** SIDE EFFECTS: None.****--*/-static void do_read (struct DNSREQ *dnsreq) {." struct IOR *ior = dnsreq->ior;, struct DNSCTX *dc = dnsreq->ctx->dnsctx; struct dsc$descriptor dsc; unsigned int status;% status = ior->iosb.iosb_w_status;  if (OK(status)) {dA INIT_SDESC(dsc, dnsreq->query_rbufsize, dnsreq->query_rbuf);iA status = netlib_read(&ior->ctx, &dsc, 0, 0, 0, &dc->timeout, : &ior->iosb, query_completion, dnsreq); }o if (OK(status)) return;y% ior->iosb.iosb_w_status = status;d query_completion(dnsreq);y} /* do_read */ ÿÿf: varying_arg, longword (unsigned), write only, by referenceD** bufsize: word_unsigned, word (unsigned), read only, by referenceH** flags: mask_longword, longword (unsigned), read only, by referenceK** à NETLIB_SRC.BCK$ç [NETLIB]LINEMODE.C;20S#–Öð*[NETLIB]LINEMODE.C;20+,$.#/€ 4S# Š-ç 0ª123KÿPWO!56,„]óú›7núš]óú›89G€HˆªJÿ/***++** FACILITY: NETLIB**1** ABSTRACT: Line-mode send and receive routines**** MODULE DESCRIPTION:**<** This module contains routines for sending and receivingD** "lines" of ASCII data, with CR/LF terminators at the end of eachC** line. It is layered on top of the raw NETLIB_READ/NETLIB_WRITEC** routines, and contains no code dependent on a particular TCP/IPC** implementation. They do assume, however, that the TCP protocol#** is being used, rather than UDP.****** AUTHOR: M. Madison<** COPYRIGHT © 1994, 1997, 1998 MADGOAT SOFTWARE."** ALL RIGHTS RESERVED.**** CREATION DATE: 22-OCT-1994**** MODIFICATION HISTORY:**1** 22-OCT-1994 V1.0 Madison Initial coding.9** 09-JAN-1995 V1.0-1 Madison Read data in 1K chunks.D** 11-JAN-1995 V1.0-2 Madison Fix timeout reference in readline.M** 13-JAN-1995 V1.0-3 Madison Fix split CR/LF handling in parse_out_line.4** 25-JAN-1995 V1.0-4 Madison Fix for CR w/o LF.H** 31-AUG-1995 V1.0-5 Madison Change writeline to write entire line,<** including terminator, in one write.:** Works around cc:Mail gateway bug.N** 19-JAN-1997 V1.0-6 Madison Async read should return NETLIB_READ status.R** 01-JUN-1997 V1.0-7 Madison Catch NETLIB_READ status in readline_continue().O** 27-NOV-1997 V1.1 Madison Add NETLIB_M_FLUSH flag to netlib_readline().1** 14-DEC-1997 V1.1-1 Madison Fix flush code.K** 02-JAN-1998 V1.1-2 Madison Make relaxed line mode even more relaxed.**--*/#include "netlib.h"/*** Forward declarations*/O unsigned int netlib_readline(struct CTX **xctx, struct dsc$descriptor *dsc,@ unsigned short *retlen, unsigned int *flagp,> TIME *timeout, struct NETLIBIOSBDEF *iosb,4 void (*astadr)(), void *astprm);3 static void readline_continue(struct IOR *ior);J static int parse_out_line(struct CTX *ctx, struct dsc$descriptor *dsc,, unsigned short *retlen);P unsigned int netlib_writeline(struct CTX **xctx, struct dsc$descriptor *dsc,1 struct NETLIBIOSBDEF *iosb,6 void (*astadr)(), void *astprm);2 static void writeline_finish(struct IOR *ior);/*** OWN storage*/% static $DESCRIPTOR(crlf, "\r\n");/*** External references*/= unsigned int netlib_read(struct CTX **xctx, void *, ...);> unsigned int netlib_write(struct CTX **xctx, void *, ...); /***++** ROUTINE: netlib_readline**** FUNCTIONAL DESCRIPTION:**A** Reads in a line. The terminating CR/LF pair is not includedC** in the data returned to the caller. The caller may specify theE** NETLIB_M_ALLOW_LF flag to permit interoperation with senders thatB** may erroneously terminate lines with just linefeeds instead of** CR/LF pairs.**B** RETURNS: cond_value, longword (unsigned), write only, by value**** PROTOTYPE:**C** NETLIB_READLINE ctx, dsc [,retlen] [,flag] [,timeout] [,iosb])** [,astadr] [,astprm]**M** ctx: NETLIB session context, longword (unsigned), modify, by referenceD** dsc: char_string, character string, write only, by descriptorD** retlen: word_unsigned, word (unsigned), write only, by referenceG** flag: mask_longword, longword (unsigned), read only, by referenceC** timeout: delta_time, quadword (signed), read only, by reference?** iosb: IO_status_block, quadword, write only, by referenceD** astadr: ast_procedure, procedure entry mask, CALL , by reference>** astprm: user_arg, longword (unsigned), read only, by value**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: See code.**** SIDE EFFECTS: None.****--*/Lunsigned int netlib_readline (struct CTX **xctx, struct dsc$descriptor *dsc,@ unsigned short *retlen, unsigned int *flagp,> TIME *timeout, struct NETLIBIOSBDEF *iosb,5 void (*astadr)(), void *astprm) { struct CTX *ctx; struct NETLIBIOSBDEF myiosb; struct dsc$descriptor sdsc; unsigned int status; unsigned short len; int argc; VERIFY_CTX(xctx, ctx) SETARGCOUNT(argc);% if (argc < 2) return SS$_INSFARG;D if (argc < 4 || flagp == 0) ctx->line_flags = NETLIB_M_ALLOW_LF;" else ctx->line_flags = *flagp; if (ctx->linebuf == 0) {. static unsigned int size = CTX_S_LINEBUF;/ status = lib$get_vm(&size, &ctx->linebuf);$ if (!OK(status)) return status; ctx->line_remain = 0;4 ctx->linebufp = ctx->lineanchor = ctx->linebuf; } len = 0; while (1) {* if (parse_out_line(ctx, dsc, &len)) { status = SS$_NORMAL; break; }A INIT_SDESC(sdsc, CTX_S_LINEBUF-(ctx->linebufp-ctx->linebuf)," ctx->linebufp);< if (sdsc.dsc$w_length > 1024) sdsc.dsc$w_length = 1024;# if (argc > 6 && astadr != 0) { struct IOR *ior;B GET_IOR(ior, ctx, iosb, astadr, (argc > 7) ? astprm : 0);# ctx->line_retlen = retlen; ctx->line_dsc = dsc;$ ctx->line_tmo = timeout;F return netlib_read(xctx, &sdsc, 0, 0, 0, timeout, &ior->iosb,, readline_continue, ior); }S status = netlib_read(xctx, &sdsc, 0, 0, 0, (argc > 4) ? timeout : 0, &myiosb); if (!OK(status)) break;, ctx->line_remain = myiosb.iosb_w_count; } /* while *// if (argc > 2 && retlen != 0) *retlen = len; if (argc > 5 && iosb != 0) {" iosb->iosb_w_status = status; iosb->iosb_w_count = len; }" if (argc > 6 && astadr != 0) {4 sys$dclast(astadr, (argc > 7) ? astprm : 0, 0); return SS$_NORMAL; } return status;} /* netlib_readline */ /***++** ROUTINE: readline_continue**** FUNCTIONAL DESCRIPTION:**D** Internal routine for coninuation of a line-mode read operation.N** Continues reading data until the line termination sequence is encountered.J** Completes the operation by returning the line (without terminators) to** the caller.**** RETURNS: void**** PROTOTYPE:**** READLINE_CONTINUE ior**L** ior: struct IOR, internal I/O request structure, modify, by reference**** IMPLICIT INPUTS: None.**** IMPLICIT OUTPUTS: None.**** COMPLETION CODES: None.**** SIDE EFFECTS: None.****--*/1static void readline_continue (struct IOR *ior) { struct CTX *ctx = ior->ctx; struct dsc$descriptor sdsc; unsigned int status; unsigned short len;' if (!OK(ior->iosb.iosb_w_status)) { if (ior->iosbp != 0) {$ ior->iosbp->iosb_w_status =" ior->iosb.iosb_w_status;& ior->iosbp->iosb_w_count = 0; }8 if (ctx->line_retlen != 0) *(ctx->line_retlen) = 0;7 if (ior->astadr != 0) (*ior->astadr)(ior->astprm); FREE_IOR(ior); return; }. ctx->line_remain = ior->ioà