db_glue.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 516 行

C
516
字号
#ifndef lintstatic	char	*sccsid = "@(#)db_glue.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1984-1990 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Copyright (c) 1986 Regents of the University of California *	All Rights Reserved * static char sccsid[] = "@(#)db_glue.c	4.2 (Berkeley) 1/14/89"; *//* * Modification History: * * 28-Feb-90	sue *	Increased timeout on second connect in icmp_ping() from *	2 to 30 seconds. * * 7-Feb-90	bbrown *	Added 4.8.2 and Kerberos */#include <sys/param.h>#include <sys/time.h>#include <sys/stat.h>#include <netinet/in.h>#include <stdio.h>#include <syslog.h>#include <ctype.h>#include <netdb.h>#include <arpa/nameser.h>#ifdef ULTRIXFUNC#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#include <resolv.h>#include <sys/socket.h>#include <netinet/in.h>#include <errno.h>#endif ULTRIXFUNC#include "ns.h"#include "db.h"#ifdef ULTRIXFUNCextern struct protoent *getprotoent_local();extern struct servent *getservent_local();extern struct protoent *getprotobyname_local();#define MAXPACKET       4096			/* max packet size */extern int errno;#endif ULTRIXFUNCstruct valuelist {	struct valuelist *next, *prev;	char	*name;	char	*proto;	short	port;} *servicelist, *protolist;buildservicelist(){	struct servent *sp;	struct valuelist *slp;#ifdef ULTRIXFUNC	setservent_local(1);	while (sp = getservent_local()) {#else ULTRIXFUNC	setservent(1);	while (sp = getservent()) {#endif ULTRIXFUNC		slp = (struct valuelist *)malloc(sizeof(struct valuelist));		slp->name = savestr(sp->s_name);		slp->proto = savestr(sp->s_proto);		slp->port = ntohs((u_short)sp->s_port);		slp->next = servicelist;		slp->prev = NULL;		if (servicelist)			servicelist->prev = slp;		servicelist = slp;	}#ifdef ULTRIXFUNC	endservent_local();#else ULTRIXFUNC	endservent();#endif ULTRIXFUNC}buildprotolist(){	struct protoent *pp;	struct valuelist *slp;#ifdef ULTRIXFUNC	setprotoent_local(1);	while (pp = getprotoent_local()) {#else ULTRIXFUNC	setprotoent(1);	while (pp = getprotoent()) {#endif ULTRIXFUNC		slp = (struct valuelist *)malloc(sizeof(struct valuelist));		slp->name = savestr(pp->p_name);		slp->port = pp->p_proto;		slp->next = protolist;		slp->prev = NULL;		if (protolist)			protolist->prev = slp;		protolist = slp;	}#ifdef ULTRIXFUNC	endprotoent_local();#else ULTRIXFUNC	endprotoent();#endif ULTRIXFUNC}/* * Convert service name or (ascii) number to int. */servicenumber(p)	char *p;{	return (findservice(p, &servicelist));}/* * Convert protocol name or (ascii) number to int. */protocolnumber(p)	char *p;{	return (findservice(p, &protolist));}findservice(s, list)	register char *s;	register struct valuelist **list;{	register struct valuelist *lp = *list;	int n;	for (; lp != NULL; lp = lp->next)		if (strcasecmp(lp->name, s) == 0) {			if (lp != *list) {				lp->prev->next = lp->next;				if (lp->next)					lp->next->prev = lp->prev;				(*list)->prev = lp;				lp->next = *list;				*list = lp;			}			return(lp->port);		}	(void) sscanf(s, "%d", &n);	if (n <= 0)		n = -1;	return(n);}struct servent *cgetservbyport(port, proto)	u_short port;	char *proto;{	register struct valuelist **list = &servicelist;	register struct valuelist *lp = *list;	static struct servent serv;	port = htons(port);	for (; lp != NULL; lp = lp->next) {		if (port != lp->port)			continue;		if (strcasecmp(lp->proto, proto) == 0) {			if (lp != *list) {				lp->prev->next = lp->next;				if (lp->next)					lp->next->prev = lp->prev;				(*list)->prev = lp;				lp->next = *list;				*list = lp;			}			serv.s_name = lp->name;			serv.s_port = htons((u_short)lp->port);			serv.s_proto = lp->proto;			return(&serv);		}	}	return(0);}struct protoent *cgetprotobynumber(proto)	register int proto;{	register struct valuelist **list = &protolist;	register struct valuelist *lp = *list;	static struct protoent prot;	for (; lp != NULL; lp = lp->next)		if (lp->port == proto) {			if (lp != *list) {				lp->prev->next = lp->next;				if (lp->next)					lp->next->prev = lp->prev;				(*list)->prev = lp;				lp->next = *list;				*list = lp;			}			prot.p_name = lp->name;			prot.p_proto = lp->port;			return(&prot);		}	return(0);}char *protocolname(num)	int num;{	static	char number[8];	struct protoent *pp;	pp = cgetprotobynumber(num);	if(pp == 0)  {		(void) sprintf(number, "%d", num);		return(number);	}	return(pp->p_name);}char *servicename(port, proto)	u_short port;	char *proto;{	static	char number[8];	struct servent *ss;	ss = cgetservbyport(htons(port), proto);	if(ss == 0)  {		(void) sprintf(number, "%d", port);		return(number);	}	return(ss->s_name);}#ifdef ULTRIXFUNC#define ICMP_PACK_SZ 64/* icmp_ping * *	This routine was developed from ping.c source * * Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet * will be added on by the kernel.  The ID field is our UNIX process ID, * and the sequence number is an ascending integer.  The first 8 bytes * of the data portion are used to hold a UNIX "timeval" struct in VAX * byte-order, to compute the round-trip time. * */icmp_ping(addr)	struct in_addr	*addr;{	static int s;	static int cc;	static int ident;	static icmp_init = 0;	static struct sockaddr_in whereto;/* Who to ping */	static u_char outpack[MAXPACKET];	static u_char inpack[MAXPACKET];	struct protoent *proto;	struct timeval *tp = (struct timeval *) &outpack[8];	struct timeval timeout;	struct timezone tz;	/* leftover */		struct ip *ip = (struct ip *) inpack;	struct icmp *icp = (struct icmp *) outpack;	struct sockaddr_in from;	int fromlen = sizeof (from);	int i;	int size;	int len = sizeof (inpack);	int looper;	int readfd, nfound;	if(!icmp_init) {		register u_char *datap = &outpack[8+sizeof(struct timeval)];		bzero( (char *)&whereto, sizeof(struct sockaddr) );		whereto.sin_family = AF_INET;		ident = getpid() & 0xFFFF;		if ((proto = getprotobyname_local("icmp")) == NULL) {			syslog(LOG_ERR, "icmp_ping: protobyname error");			return(-1);		}		if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {			syslog(LOG_ERR, "icmp_ping: socket error");			return(-1);		}		if( s >= 32 ) {			syslog(LOG_ERR, "icmp_ping: socket leak exists");			close(s);			return(-1);		}			icp->icmp_type = ICMP_ECHO;		icp->icmp_code = 0;		icp->icmp_cksum = 0;		icp->icmp_seq = 0;		icp->icmp_id = ident;		/* ID */		cc = ICMP_PACK_SZ;		/* skips ICMP portion */		for( i=8; i < ICMP_PACK_SZ - 8; i++)			*datap++ = i;		icmp_init = 1;	}	whereto.sin_addr = *addr;	icp->icmp_seq++;	gettimeofday( tp, &tz );	icp->icmp_cksum = 0;	/* Compute ICMP checksum here */	icp->icmp_cksum = in_cksum( icp, cc );	for(looper = 0; looper < 10; looper++) {		len = sizeof (inpack);		i = sendto(s, outpack, cc, 0, &whereto,				sizeof(struct sockaddr) );		if( i < 0 || i != cc )  {			syslog(LOG_ERR,"zoneref: sendto error: %d, %d", i, cc);			return(-1);		}		readfd = 1<<s;		timeout.tv_sec = 0;		timeout.tv_usec = 500000;		if((nfound = select(s+1, &readfd, (int *)NULL, (int *)NULL, &timeout))			== 0) {			i = sendto( s, outpack, cc, 0, &whereto,				sizeof(struct sockaddr) );			if( i < 0 || i != cc )  {				syslog(LOG_ERR,"zoneref: sendto error: %d, %d", i, cc);				return(-1);			}			readfd = 1<<s;			timeout.tv_sec = 30;			timeout.tv_usec = 0;			if((nfound = select(s + 1, &readfd, (int *)NULL, (int *)NULL,				&timeout)) == 0) {#ifdef DEBUG				if(debug)					fprintf(ddt, "select failed in icmp_ping\n");#endif DEBUG				return(-1);			}		}		errno = 0;		if ( (size = recvfrom(s, inpack, len, 0, &from, &fromlen)) < 0) {			if( errno == EINTR ) {				if ( (size = recvfrom(s, inpack, len, 0,						&from, &fromlen)) < 0) {#ifdef DEBUG					if(debug)						fprintf(ddt, "recvfrom failed in icmp_ping, errno %d, size %d\n", errno, size);#endif DEBUG					return(-1);				}			} else {#ifdef DEBUG				if(debug)					fprintf(ddt, "recvfrom failed in icmp_ping, errno %d, size %d\n", errno, size);#endif DEBUG				return(-1);			}		}		len = ip->ip_hl << 2;		if (size < len + ICMP_MINLEN) {#ifdef DEBUG			if(debug)				fprintf(ddt, "len problem in icmp_ping, len %d, size %d\n", len, size);#endif DEBUG			return(-1);		}		icp = (struct icmp *)(inpack + len);		if( icp->icmp_id == ident ) {			break;			/* 'Twas our ECHO */		}		/* 'Twas not our ECHO */#ifdef DEBUG		if(debug)			fprintf(ddt, "Was not our echo in icmp_ping, msg id %d, our id %d\n", (int)icp->icmp_id, (int)ident);#endif DEBUG	}	if( icp->icmp_type != ICMP_ECHOREPLY ) { /*Can't get there from here*/#ifdef DEBUG		if(debug)			fprintf(ddt, "Can't get there from here in icmp_ping, type %d\n", (int)icp->icmp_type);#endif DEBUG		return(-1);	}	return(0);				/* 'Twas our ECHO */}/* *			I N _ C K S U M * * Checksum routine for Internet Protocol family headers (C Version) * */in_cksum(addr, len)u_short *addr;int len;{	register int nleft = len;	register u_short *w = addr;	register u_short answer;	register int sum = 0; 	u_short odd_byte = 0;	/*	 *  Our algorithm is simple, using a 32 bit accumulator (sum),	 *  we add sequential 16 bit words to it, and at the end, fold	 *  back all the carry bits from the top 16 bits into the lower	 *  16 bits.	 */	while( nleft > 1 )  {		sum += *w++;		nleft -= 2;	}	/* mop up an odd byte, if necessary */	if( nleft == 1 ) {               *(u_char *)(&odd_byte) = *(u_char *)w;               sum += odd_byte;	}	/*	 * add back carry outs from top 16 bits to low 16 bits	 */	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */	sum += (sum >> 16);			/* add carry */	answer = ~sum;				/* truncate to 16 bits */	return (answer);}#endif ULTRIXFUNC

⌨️ 快捷键说明

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