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

📄 send.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1985, 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement:  ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintstatic char Version[] = "@(#)send.c	e07@nikhef.nl (Eric Wassenaar) 930915";#endif#if defined(apollo) && defined(lint)#define __attribute(x)#endif#include <stdio.h>#include <errno.h>#include <setjmp.h>#include <signal.h>#include <sys/time.h>#include <sys/types.h>		/* not always automatically included */#include <sys/param.h>#include <sys/socket.h>#include <netinet/in.h>#undef NOERROR			/* in <sys/streams.h> on solaris 2.x */#include <arpa/nameser.h>#include <resolv.h>#include "port.h"		/* various portability definitions */#define input			/* read-only input parameter */#define output			/* modified output parameter */#define bitset(a,b)	(((a) & (b)) != 0)#define setalarm(n)	(void) alarm((unsigned int)n)extern int errno;extern res_state_t _res;	/* defined in res_init.c */static int timeout;		/* connection read timeout *//* extern */char *inet_ntoa		PROTO((struct in_addr));/* send.c */#ifdef HOST_RES_SENDint res_send		PROTO((char *, int, char *, int));#ifndef lintvoid _res_close		PROTO((void));#endifstatic int send_stream	PROTO((struct sockaddr_in *, char *, int, char *, int));static int send_dgram	PROTO((struct sockaddr_in *, char *, int, char *, int));#endif /*HOST_RES_SEND*/static sigtype_t timer	PROTO((int));int _res_connect	PROTO((int, struct sockaddr_in *, int));int _res_write		PROTO((int, char *, int));int _res_read		PROTO((int, char *, int));static int recvsock	PROTO((int, char *, int));void _res_setaddr	PROTO((struct sockaddr_in *, char *));void _res_perror	PROTO((char *));#ifdef HOST_RES_SEND/*** RES_SEND -- Send nameserver query and retrieve answer** -----------------------------------------------------****	Returns:**		Length of nameserver answer buffer, if obtained.**		-1 if an error occurred (errno set appropriately).****	This is a simplified version of the BIND 4.8.3 res_send().**	- Always use connected datagrams to get proper error messages.**	- Do not only return ETIMEDOUT or ECONNREFUSED in datagram mode.**	- Never leave a connection open after we got an answer.**	- No special ECONNRESET handling when using virtual circuits.*/intres_send(query, querylen, answer, anslen)input char *query;			/* address of formatted query buffer */input int querylen;			/* length of query buffer */output char *answer;			/* address of buffer to store answer */input int anslen;			/* maximum size of answer buffer */{	HEADER *bp = (HEADER *)answer;	struct sockaddr_in *sin;	int v_circuit;			/* virtual circuit or datagram switch */	register int try, ns;	register int n;	/* make sure resolver has been initialized */	if (!bitset(RES_INIT, _res.options) && res_init() == -1)		return(-1);	if (bitset(RES_DEBUG, _res.options))	{		printf("res_send()\n");		fp_query(query, stdout);	}	/* use virtual circuit if requested or if necessary */	v_circuit = bitset(RES_USEVC, _res.options) || (querylen > PACKETSZ);/* * Do _res.retry attempts for each of the _res.nscount addresses. */	for (try = 0; try < _res.retry; try++)	{	    for (ns = 0; ns < _res.nscount; ns++)	    {		sin = &nslist(ns);		_res_setaddr(sin, (char *)NULL);retry:		if (bitset(RES_DEBUG, _res.options))			printf("Querying server (# %d) %s address = %s\n", ns+1,			    v_circuit ? "tcp" : "udp", inet_ntoa(sin->sin_addr));		if (v_circuit)		{			/* at most one attempt per server */			try = _res.retry;			/* connect via virtual circuit */			n = send_stream(sin, query, querylen, answer, anslen);		}		else		{			/* set datagram read timeout for recvsock */			timeout = (_res.retrans << try);			if (try > 0)				timeout /= _res.nscount;			if (timeout <= 0)				timeout = 1;			/* connect via datagram */			n = send_dgram(sin, query, querylen, answer, anslen);			/* check truncation; use v_circuit with same server */			if (n > 0 && bp->tc)			{				if (bitset(RES_DEBUG, _res.options))					(void) fprintf(stderr, "truncated answer\n");				if (!bitset(RES_IGNTC, _res.options))				{					v_circuit = 1;					goto retry;				}			}		}		if (n <= 0)			continue;		if (bitset(RES_DEBUG, _res.options))		{			printf("got answer:\n");			fp_query(answer, stdout);		}		/* we have an answer; clear possible error condition */		errno = 0;		return(n);	    }	}	return(-1);}/* * Note that this private version of res_send() is not only called * directly by 'host' but also indirectly by gethostbyname() or by * gethostbyaddr() via their resolver interface routines. *//* * Provide dummy routine to prevent the real res_send() to be loaded. * This one is actually only called by endhostent() to close a socket * that was requested to stay open. But in this version sockets are * always closed after use. */#ifndef lintvoid_res_close(){}#endif/*** SEND_STREAM -- Query nameserver via virtual circuit** ---------------------------------------------------****	Returns:**		Length of nameserver answer buffer, if obtained.**		-1 if an error occurred.****	Note that connect() is the call that is allowed to fail**	under normal circumstances. All other failures generate**	an unconditional error message.*/static intsend_stream(addr, query, querylen, answer, anslen)input struct sockaddr_in *addr;		/* the server address to connect to */input char *query;			/* address of formatted query buffer */input int querylen;			/* length of query buffer */output char *answer;			/* address of buffer to store answer */input int anslen;			/* maximum size of answer buffer */{	int sock;	register int n;/* * Setup a virtual circuit connection. */	sock = socket(AF_INET, SOCK_STREAM, 0);	if (sock < 0)	{		_res_perror("socket");		return(-1);	}	if (_res_connect(sock, addr, sizeof(*addr)) < 0)	{		if (bitset(RES_DEBUG, _res.options))			_res_perror("connect");		(void) close(sock);		return(-1);	}	if (bitset(RES_DEBUG, _res.options))		printf("connected to %s\n", inet_ntoa(addr->sin_addr));/* * Send the query buffer. */	if (_res_write(sock, query, querylen) < 0)	{		(void) close(sock);		return(-1);	}/* * Read the answer buffer. */	n = _res_read(sock, answer, anslen);	if (n <= 0)	{		(void) close(sock);		return(-1);	}/* * Never leave the socket open. */	(void) close(sock);	return(n);}/*** SEND_DGRAM -- Query nameserver via datagram** -------------------------------------------****	Returns:**		Length of nameserver answer buffer, if obtained.**		-1 if an error occurred.****	Inputs:**		The global variable timeout should have been**		set with the desired timeout value in seconds.****	Sending to a nameserver datagram port with no nameserver running**	will cause an ICMP port unreachable message to be returned. If the**	socket is connected, we get an ECONNREFUSED error on the next socket**	operation, and select returns if the error message is received.**	Also, we get ENETUNREACH or EHOSTUNREACH errors if appropriate.**	We thus get a proper error status before timing out.**	This method usually works only if BSD >= 43.****	Note that send() and recv() are now the calls that are allowed**	to fail under normal circumstances. All other failures generate**	an unconditional error message.*/static intsend_dgram(addr, query, querylen, answer, anslen)input struct sockaddr_in *addr;		/* the server address to connect to */input char *query;			/* address of formatted query buffer */input int querylen;			/* length of query buffer */output char *answer;			/* address of buffer to store answer */input int anslen;			/* maximum size of answer buffer */{	HEADER *qp = (HEADER *)query;	HEADER *bp = (HEADER *)answer;	int sock;	register int n;/* * Setup a connected datagram socket. */	sock = socket(AF_INET, SOCK_DGRAM, 0);	if (sock < 0)	{		_res_perror("socket");		return(-1);	}	if (connect(sock, (struct sockaddr *)addr, sizeof(*addr)) < 0)	{		_res_perror("connect");		(void) close(sock);		return(-1);	}/* * Send the query buffer. */	if (send(sock, query, querylen, 0) != querylen)	{		if (bitset(RES_DEBUG, _res.options))

⌨️ 快捷键说明

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