⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dirsend.c

📁 sock5代理服务器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  Copyright (c) 1989, 1990, 1991 by the University of Washington           *//*                                                                           *//*   For copying and distribution information, please see the file           *//*   <copyright.h>.                                                          *//* If you're going to hack on this, I'd suggest using unifdef with -UCUTCP   *//* for your working copy.  When you've got your changes done, come back and  *//* add them into this main file.  It's getting pretty nasty down there.      */#include "pmachine.h"/* THIS does FD_SET etc on AT&T 3b2s.                                        */#ifdef u3b2# include <sys/inet.h> #endif /* Interactive UNIX keeps some of the socket definitions in funny places.    */#ifdef ISC# include <net/errno.h>#endif /* ISC */#include "pfs.h"#include "pprot.h"#include "pcompat.h"#include "perrno.h"static int notprived = 0;extern int errno;extern int perrno;extern int rdgram_priority;#ifdef DEBUGextern int pfs_debug;#endifextern int pfs_disable_flag;extern int verbose;char	*nlsindex();#define max(X, Y)  ((X) > (Y) ? (X) : (Y))static int		dir_udp_port = 0;	/* Remote UDP port number */static unsigned short	next_conn_id = 0;static int client_dirsrv_timeout = CLIENT_DIRSRV_TIMEOUT;static int client_dirsrv_retry = CLIENT_DIRSRV_RETRY; /* These were parameters to dirsend() */static PTEXT pkt;static char *hostname;static struct sockaddr_in *hostaddr;/* These were locals in dirsend(). Note that the initializations here * are really meaningless since we have to redo them for each call to * dirsend() since they were formerly automatically initialized. */static PTEXT		first = NULL;	/* First returned packet	 */static PTEXT		next;		/* The one we are waiting for 	 */static PTEXT		vtmp;           /* For reorganizing linked list  */static PTEXT		comp_thru;	/* We have all packets though    */static int		lp = -1;	/* Opened UDP port	         */static int		hdr_len;	/* Header Length                 */static int		nd_pkts;	/* Number of packets we want     */static int		no_pkts;	/* Number of packets we have     */static int		pkt_cid;        /* Packet connection identifier  */static unsigned short	this_conn_id;	/* Connection ID we are using    */static unsigned short	recvd_thru;	/* Received through              */static short		priority;	/* Priority for request          */static short		one = 0;	/* Pointer to value 1            */static short		zero = 0;	/* Pointer to value 0		 */static char		*seqtxt;	/* Pointer to text w/ sequence # */static struct sockaddr_in  us;		/* Our address                   */static struct sockaddr_in  to;		/* Address to send query	 */static struct sockaddr_in  from;	/* Reply received from		 */static int		from_sz;	/* Size of from structure	 */static struct hostent	*host;		/* Host info from gethostbyname  */static long		newhostaddr;    /* New host address from *host   */static int		req_udp_port=0; /* Requested port (optional)     */static char		*openparen;	/* Delimits port in name         */static char		hostnoport[500];/* Host name without port        */static int		ns;		/* Number of bytes actually sent */static int		nr;		/* Number of bytes received      */static SELECTARG	readfds;	/* Used for select		 */static int		tmp;static char		*ctlptr;	/* Pointer to control field      */static short		stmp;		/* Temp short for conversions    */static int		backoff;	/* Server requested backoff      */static unsigned char	rdflag11;	/* First byte of flags (bit vect)*/static unsigned char	rdflag12;	/* Second byte of flags (int)    */static int		scpflag = 0;	/* Set if any sequencd cont pkts */static int		ackpend = 0;    /* Acknowledgement pending      */static int		gaps = 0;	/* Gaps present in recvd pkts   */static struct timeval	timeout;	/* Time to wait for response    */static struct timeval	ackwait;	/* Time to wait before acking   */static struct timeval	gapwait;	/* Time to wait b4 filling gaps */static struct timeval	*selwait;	/* Time to wait for select      */static int		retries;	/* was = client_dirsrv_retry    */char   to_hostname[512];		/* lmjm: saves inet_ntoa() str  *//* These are added so dirsend() "blocks" properly */static PTEXT dirsendReturn;static int dirsendDone;/* And here are the values for dirsendDone */#define DSRET_DONE		1#define DSRET_SEND_ERROR	-1#define DSRET_RECV_ERROR	-2#define DSRET_SELECT_ERROR	-3#define DSRET_TIMEOUT		-4#define DSRET_ABORTED		-5/* New procedures to break up dirsend() */static int initDirsend();static void retryDirsend(), keepWaitingDirsend();static void timeoutProc();static void readProc();/* Wrappers around X calls to allow non-X usage */static void processEvent();/* Extra stuff for the asynchronous X version of dirsend() */typedef char *XtPointer;typedef char *XtInputId;typedef char *XtIntervalId;static XtInputId inputId;static XtIntervalId timerId = (XtIntervalId)0;/* * dirsend - send packet and receive response * *   DIRSEND takes a pointer to a structure of type PTEXT, a hostname, *   and a pointer to a host address.  It then sends the supplied *   packet off to the directory server on the specified host.  If *   hostaddr points to a valid address, that address is used.  Otherwise, *   the hostname is looked up to obtain the address.  If hostaddr is a *   non-null pointer to a 0 address, then the address will be replaced *   with that found in the hostname lookup. * *   DIRSEND will wait for a response and retry an appropriate *   number of times as defined by timeout and retries (both static *   variables).  It will collect however many packets form the reply, and *   return them in a structure (or structures) of type PTEXT. * *   DIRSEND will free the packet that it is presented as an argument. *   The packet is freed even if dirsend fails. */PTEXTdirsend(pkt_p,hostname_p,hostaddr_p)    PTEXT pkt_p;    char *hostname_p;    struct sockaddr_in	*hostaddr_p;{    /* copy parameters to globals since other routines use them */    pkt = pkt_p;    hostname = hostname_p;    hostaddr = hostaddr_p;    /* Do the initializations of formerly auto variables */    first = NULL;    lp = -1;    one = 0;    zero = 0;    req_udp_port=0;    scpflag = 0;    ackpend = 0;    gaps = 0;    retries = client_dirsrv_retry;    if (initDirsend() < 0)	return(NULL);    /* set the first timeout */    retryDirsend();    dirsendReturn = NULL;    dirsendDone = 0;    /* Until one of the callbacks says to return, keep processing events */    while (!dirsendDone)	processEvent();    /* Return whatever we're supposed to */    return(dirsendReturn);}/*	-	-	-	-	-	-	-	-	*//* This function does all the initialization that used to be done at the * start of dirsend(), including opening the socket descriptor "lp". It * returns the descriptor if successful, otherwise -1 to indicate that * dirsend() should return NULL immediately. */static intinitDirsend(){    if(one == 0) one = htons((short) 1);    priority = htons(rdgram_priority);    timeout.tv_sec = client_dirsrv_timeout;    timeout.tv_usec = 0;    ackwait.tv_sec = 0;    ackwait.tv_usec = 500000;    gapwait.tv_sec = (client_dirsrv_timeout < 5 ? client_dirsrv_timeout : 5);    gapwait.tv_usec = 0;    comp_thru = NULL;    perrno = 0;    nd_pkts = 0;    no_pkts = 0;    pkt_cid = 0;    /* Find first connection ID */    if(next_conn_id == 0) {	srand(getpid()+time(0)); /* XXX: arg ok, but not right type. */	next_conn_id = rand();    }    /* If necessary, find out what udp port to send to */    if (dir_udp_port == 0) {        register struct servent *sp;	tmp = pfs_enable; pfs_enable = PMAP_DISABLE;#ifdef USE_ASSIGNED_PORT	/* UCX needs 0 & -1 */        sp = getservbyname("prospero","udp");	if (sp == (struct servent *)0 || sp == (struct servent *)-1) {#ifdef DEBUG	    if (pfs_debug)		fprintf(stderr, "dirsrv: udp/prospero unknown service - using %d\n", 			PROSPERO_PORT);#endif	    dir_udp_port = htons((u_short) PROSPERO_PORT);        }#else	/* UCX needs 0 & -1 */        sp = getservbyname("dirsrv","udp");	if (sp == (struct servent *)0 || sp == (struct servent *)-1) {#ifdef DEBUG	    if (pfs_debug)		fprintf(stderr, "dirsrv: udp/dirsrv unknown service - using %d\n", 			DIRSRV_PORT);#endif	    dir_udp_port = htons((u_short) DIRSRV_PORT);        }#endif	else dir_udp_port = sp->s_port;	pfs_enable = tmp;#ifdef DEBUG        if (pfs_debug > 3)            fprintf(stderr,"dir_udp_port is %d\n", ntohs(dir_udp_port));#endif    }    /* If we were given the host address, then use it.  Otherwise  */    /* lookup the hostname.  If we were passed a host address of   */    /* 0, we must lookup the host name, then replace the old value */    if(!hostaddr || (hostaddr->sin_addr.s_addr == 0)) {	/* I we have a null host name, return an error */	if((hostname == NULL) || (*hostname == '\0')) {#ifdef DEBUG            if (pfs_debug)                fprintf(stderr, "dirsrv: Null hostname specified\n");#endif	    perrno = DIRSEND_BAD_HOSTNAME;	    ptlfree(pkt);            /* return(NULL); */	    return(-1);	}	/* If a port is included, save it away */	if((openparen = index(hostname,'('))) {	    sscanf(openparen+1,"%d",&req_udp_port);	    strncpy(hostnoport,hostname,400);	    if((openparen - hostname) < 400) {		*(hostnoport + (openparen - hostname)) = '\0';		hostname = hostnoport;	    }	}	tmp = pfs_enable; pfs_enable = PMAP_DISABLE;	if((host = gethostbyname(hostname)) == NULL) {	    pfs_enable = tmp;	    /* Check if a numeric address */	    newhostaddr = inet_addr(hostname);	    if(newhostaddr == -1) {#ifdef DEBUG		if (pfs_debug)		  fprintf(stderr, "dirsrv: Can't resolve host %s\n",hostname);#endif		perrno = DIRSEND_BAD_HOSTNAME;		ptlfree(pkt);		/* return(NULL); */		return(-1);	    }	    bzero((char *)&to, S_AD_SZ);	    to.sin_family = AF_INET;	    bcopy((char *)&newhostaddr, (char *)&to.sin_addr, 4);	    if(hostaddr) bcopy((char *)&to, (char *)hostaddr, S_AD_SZ);	}	else {	    pfs_enable = tmp;	    bzero((char *)&to, S_AD_SZ);	    to.sin_family = host->h_addrtype;	    bcopy((char *)host->h_addr, (char *)&to.sin_addr, host->h_length);	    if(hostaddr) bcopy((char *)&to, (char *)hostaddr, S_AD_SZ);	}    }    else bcopy((char *)hostaddr, (char *)&to, S_AD_SZ);    /* lmjm: Save away the hostname */    strncpy(to_hostname, inet_ntoa(to.sin_addr), sizeof(to_hostname)-1);    if(req_udp_port) to.sin_port = htons(req_udp_port);    else to.sin_port = dir_udp_port;    /* If a port was specified in hostaddr, use it, otherwise fill it in */    if(hostaddr) {	if(hostaddr->sin_port) to.sin_port = hostaddr->sin_port;	else hostaddr->sin_port = to.sin_port;    }    /* Must open a new port each time. we do not want to see old */    /* responses to messages we are done with                    */    if ((lp = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {#ifdef DEBUG        if (pfs_debug)            fprintf(stderr,"dirsrv: Can't open socket\n");#endif	perrno = DIRSEND_UDP_CANT;	ptlfree(pkt);        /* return(NULL); */	return(-1);    }    /* Try to bind it to a privileged port - loop through candidate */    /* ports trying to bind.  If failed, that's OK, we will let the */    /* system assign a non-privileged port later                    */    if(!notprived) {	for(tmp = PROS_FIRST_PRIVP; tmp < PROS_FIRST_PRIVP+PROS_NUM_PRIVP; 	    tmp++) {	    bzero((char *)&us, sizeof(us));	    us.sin_family = AF_INET;	    us.sin_port = htons((u_short) tmp);	    if (bind(lp, (struct sockaddr *)&us, sizeof(us))) {		if(errno != EADDRINUSE) {		    notprived++;		    break;		}	    }	    else break;	}    }#ifndef USE_V3_PROT    /* Add header */    if(rdgram_priority) {	pkt->start -= 15;	pkt->length += 15;	*(pkt->start) = (char) 15;	bzero(pkt->start+9,4);	*(pkt->start+11) = 0x02;	bcopy((char *)&priority, pkt->start+13,2);    }    else {	pkt->start -= 9;	pkt->length += 9;	*(pkt->start) = (char) 9;    }    this_conn_id = htons(next_conn_id++);    if(next_conn_id == 0) next_conn_id++;    bcopy((char *)&this_conn_id, pkt->start+1,2);    bcopy((char *)&one,pkt->start+3,2);    bcopy((char *)&one,pkt->start+5,2);    bzero(pkt->start+7,2);#endif#ifdef DEBUG    if (pfs_debug > 2) {#ifndef USE_V3_PROT        if (to.sin_family == AF_INET) {	    if(req_udp_port) 		fprintf(stderr,"Sending message to %s+%d(%d)...",			to_hostname, req_udp_port, ntohs(this_conn_id));	    else fprintf(stderr,"Sending message to %s(%d)...",			 to_hostname, ntohs(this_conn_id));	}#else        if (to.sin_family == AF_INET) 	    fprintf(stderr,"Sending message to %s...", to_hostname);#endif /* USE_V3_PROT */        else            fprintf(stderr,"Sending message...");        (void) fflush(stderr);    }#endif /* DEBUG */    first = ptalloc();    next = first;    return(lp);}/*	-	-	-	-	-	-	-	-	*//* * This used to be a label to goto to retry the last packet. Now we resend * the packet and call keepWaitingDirsend() to wait for a reply. (We * call keepWaitingDirsend() because formerly the code dropped through * the keep_waiting label.) */static voidretryDirsend(){    gaps = ackpend = 0;    ns = sendto(lp,(char *)(pkt->start), pkt->length, 0, (struct sockaddr *)&to, S_AD_SZ);    if(ns != pkt->length) {#ifdef DEBUG	if (pfs_debug) {    fprintf(stderr,"\nsent only %d/%d: ",ns, pkt->length);	    perror("");	}#endif	close(lp);	perrno = DIRSEND_NOT_ALL_SENT;	ptlfree(first);	ptlfree(pkt);	/* pkt= NULL;    */  /* added by NEC NWSL */	/* return(NULL); */	dirsendReturn = NULL;	dirsendDone = DSRET_SEND_ERROR;    }#ifdef DEBUG    if (pfs_debug > 2) fprintf(stderr,"Sent.\n");#endif    keepWaitingDirsend();}/*	-	-	-	-	-	-	-	-	*//* * This used to be a label to goto to set the appropriate timeout value * and blocked in select(). Now we set selwait and the SELECTARGs to the * appropriate values, and in X register a new timeout, then return to * allow event processing. */static voidkeepWaitingDirsend(){    /* We come back to this point (by a goto) if the packet */    /* received is only part of the response, or if the     */    /* response came from the wrong host		    */#ifdef DEBUG    if (pfs_debug > 2) fprintf(stderr,"Waiting for reply...");#endif    FD_ZERO(&readfds);    FD_SET(lp, &readfds);    if(ackpend) selwait = &ackwait;    else if(gaps) selwait = &gapwait;    else selwait = &timeout;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -