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

📄 ip_misc.c

📁 MSyslog是一个允许在Linux下运行的网络系统日志程序
💻 C
字号:
/*	$CoreSDI: ip_misc.c,v 1.26 2001/12/05 20:47:56 alejo Exp $	*//* * Copyright (c) 2001, Core SDI S.A., Argentina * All rights reserved *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither name of the Core SDI S.A. 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* * ip_misc -- basic TCP/UDP/IP functions *       * Author: Alejo Sanchez for Core SDI S.A. *  */#include "config.h"#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#include <sys/types.h>#include <sys/uio.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <ctype.h>#include <errno.h>#ifdef HAVE_INTTYPES_H# include <inttypes.h>#endif#ifdef HAVE_MACHINE_ENDIAN_H# include <machine/endian.h>#endif#include <netdb.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <syslog.h>#include <unistd.h>#include "../modules.h"#include "../syslogd.h"/* recvfrom() and others like socklen_t, Irix doesn't provide it */   #ifndef HAVE_SOCKLEN_T  typedef int socklen_t;#endif#define TCP_KEEPALIVE 30	/* seconds to probe TCP connection */#define MSYSLOG_MAX_TCP_CLIENTS 100#define LISTENQ 35/* * resolv_addr: get a  host name from a generic sockaddr structure * */intresolv_addr(struct sockaddr *addr, socklen_t addrlen, char *host, int hlen,    char *port, int plen){#ifdef HAVE_GETNAMEINFO	if (getnameinfo((struct sockaddr *) addr, addrlen,	    host, hlen - 1, port, plen, 0) == 0)		return (1);#else /* no HAVE_GETNAMEINFO, old socket API */	struct hostent	*hp;	struct sockaddr_in *sin4;	sin4 = (struct sockaddr_in *) addr;	hp = gethostbyaddr((char *) &sin4->sin_addr,	    sizeof(sin4->sin_addr), sin4->sin_family);	if (hp) {		strncpy(host, hp->h_name, (unsigned) hlen - 1);		host[hlen - 1] = '\0';		if (port)			snprintf(port, (unsigned) plen, "%u", ntohs(sin4->sin_port));		return (1);	}#endif /* HAVE_GETNAMEINFO */#ifdef HAVE_INET_NTOP	switch (addr->sa_family) {	case AF_INET: {		struct sockaddr_in *caddr;		caddr = (struct sockaddr_in *) addr;		if (inet_ntop(AF_INET, &caddr->sin_addr, host, hlen) != NULL) {# ifdef HAVE_INET_NTOHS			if (ntohs(caddr->sin_port)) != 0)				snprintf(port, (unsigned) plen, "%u",				    ntohs(caddr->sin_port));# endif /* HAVE_INET_NTOHS */			return (1);		}		}	case AF_INET6: {		struct sockaddr_in6 *caddr;		caddr = (struct sockaddr_in6 *) addr;		if (inet_ntop(AF_INET6, &caddr->sin6_addr, host, hlen) != NULL) {# ifdef HAVE_INET_NTOHS			if (ntohs(caddr->sin6_port)) != 0)				snprintf(port, (unsigned) plen, "%u",				    ntohs(caddr->sin6_port));# endif /* HAVE_INET_NTOHS */			return (1);		}		}	default:		return (-1);	}#endif /* HAVE_INET_NTOP */	dprintf(MSYSLOG_SERIOUS, "resolv_addr: error resolving "	     "remote host name!\n");	if (host)		host[0] = '\0';	if (port)		port[0] = '\0';	return (-1);}/* * resolv_name: get a sockaddr address from host and port string * * NOTE: you must free the struct returned! */struct sockaddr *resolv_name(char *host, char *port, char *proto, socklen_t *salen){	struct sockaddr *sa;#ifdef HAVE_GETADDRINFO	struct addrinfo hints, *res;	int i;#if defined(HAVE_INET_ADDR) && !defined(HAVE_INET_ATON)	in_addr_t	addr;#endif	memset(&hints, 0, sizeof(hints));	hints.ai_flags = AI_PASSIVE;	hints.ai_family = AF_UNSPEC;	if (proto != NULL && strcmp(proto, "udp") == 0)		hints.ai_socktype = SOCK_DGRAM;	else		hints.ai_socktype = SOCK_STREAM;	if ( (i = getaddrinfo(host, port, &hints, &res)) != 0) {		dprintf(MSYSLOG_SERIOUS, "resolv_name: error on address "		    "to listen %s, %s: %s\n", host, port, gai_strerror(i));		return (NULL);	}	sa = (struct sockaddr *) malloc(res->ai_addrlen);	memcpy(sa, res->ai_addr, res->ai_addrlen);	*salen = res->ai_addrlen;	freeaddrinfo(res);#else	/* we are on an extremely outdated and ugly api */	struct sockaddr_in	*sin;	struct hostent *hp;	struct servent *se;	short portnum;	if (port != NULL && isdigit((int) *port)) {		portnum = strtol(port, NULL, 10);	} else if ((se = getservbyname(port == NULL? "syslog" : port,	    proto == NULL? "tcp" : proto)) != NULL) {		portnum = se->s_port;	} else		portnum = 514;#ifndef	WORDS_BIGENDIAN	portnum = htons(portnum);#endif	sin = (struct sockaddr_in *) malloc(sizeof(*sin));#ifdef HAVE_SOCKADDR_SA_LEN	sin->sin_len = sizeof(*sin);#endif	sin->sin_family = AF_INET;	sin->sin_port = portnum;	memset(&sin->sin_addr, 0, sizeof(sin->sin_addr));	if (host == NULL ||#ifdef HAVE_INET_ATONinet_aton(host, &sin->sin_addr) == 1#elif defined(HAVE_INET_ADDR)        (addr = inet_addr(host)) > 0 &&                 memcpy(&sin->sin_addr, &addr, sizeof(sin->sin_addr)) != NULL#else# error NEED RESOLVING FUNCTION, PLEASE REPORT#endif	    ) {		return ((struct sockaddr *) sin);	} else if ((hp = gethostbyname(host)) == NULL) {		dprintf(MSYSLOG_SERIOUS, "resolv_name: error "		    "resolving host address %s, %s\n", host, port);		return (NULL);	}	if (hp->h_addrtype == AF_INET) {		struct sockaddr_in *sin4;		sin4 = (struct sockaddr_in *)		    malloc(sizeof(struct sockaddr_in));		*salen = sizeof(struct sockaddr_in);#ifdef HAVE_SOCKADDR_SA_LEN		sin4->sin_len = sizeof(struct sockaddr_in);#endif		sin4->sin_port = portnum;		sin4->sin_family = AF_INET;		memcpy(&sin4->sin_addr, *hp->h_addr_list,		    sizeof(struct in_addr));		sa = (struct sockaddr *) sin4;	}#ifdef AF_INET6	else if (hp->h_addrtype == AF_INET) {		struct sockaddr_in6 *sin6;		sin6 = (struct sockaddr_in6 *)		    malloc(sizeof(*sin6));		*salen = sizeof(struct sockaddr_in);# ifdef HAVE_SOCKADDR_SA_LEN		sin6->sin6_len = sizeof(struct sockaddr_in6);# endif		sin6->sin6_port = portnum;		sin6->sin6_family = AF_INET6;		sin6->sin6_port = 0; /* this should be specified later */		memcpy(&sin6->sin6_addr, *hp->h_addr_list,		    sizeof(struct in6_addr));		sa = (struct sockaddr *) sin6;	}#endif /* AF_INET6 */	else  /* no match ?!? */		sa = NULL;#endif /* HAVE_GETADDRINFO */	return (sa);}/* * connect_tcp: connect to a remote host/port *              return the file descriptor */intconnect_tcp(char *host, char *port) {	int fd, n;	struct sockaddr *sa;	socklen_t salen;	if ( (sa = resolv_name(host, port, "tcp", &salen)) == NULL)		return (-1);	n = TCP_KEEPALIVE;	if (sa->sa_family != AF_INET#ifdef AF_INET6	    && sa->sa_family != AF_INET6#endif	    ) {		free(sa);		return (-1);	}	if ( (fd = socket(sa->sa_family, SOCK_STREAM, 0)) > -1 )		if ( (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &n,		    sizeof(n)) != 0) || (connect(fd, sa, salen) != 0) ) {			close(fd); /* couldn't set option or connect */			fd = -1;		}	free(sa);	return (fd);}/* * listen_tcp: listen on a host/port *             return the file descriptor */intlisten_tcp(char *host, char *port, socklen_t *addrlenp) {	int fd, n, r;	struct sockaddr *sa;	if ( (sa = resolv_name(host, port, "tcp", addrlenp)) == NULL)		return (-1);	n = TCP_KEEPALIVE;	r = 1;	if ( (fd = socket(sa->sa_family, SOCK_STREAM, 0)) > -1 )		if ( (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &n,		    sizeof(n)) != 0) || (setsockopt(fd, SOL_SOCKET,		    SO_REUSEADDR, &r, sizeof(r)) != 0) ||		    (bind(fd, sa, *addrlenp) != 0) ||		    (listen(fd, LISTENQ) != 0) ) {			close(fd); /* couldn't set option or connect */			fd = -1;		}	free(sa);	return (fd);}/* * accept_tcp: accept a listen file descriptor *             return the connected file descriptor */intaccept_tcp(int fd, socklen_t addrlen, char *host, int hlen, char *port,    int plen){	struct sockaddr *connsa;	int connfd;	if (addrlen < 1 || (connsa = (struct sockaddr *)	    calloc(1, addrlen)) == NULL )		return (-1);	if ((connfd = accept(fd, connsa, (socklen_t *) &addrlen)) != -1)		(void) resolv_addr(connsa, addrlen, host, hlen, port, plen);	free(connsa);	return (connfd);}/* * sock_udp: create a generic socket for sending udp packets * * NOTE: you must free the struct returned! */intsock_udp(char *host, char *port, void **addr, int *addrlen){	struct sockaddr	*sa;	if (addr == NULL || addrlen == NULL)		return (-1);	if ( (sa = resolv_name(host, port, "udp", (socklen_t *) addrlen))	    == NULL)		return (-1);	*addr = sa;	return (socket(sa->sa_family, SOCK_DGRAM, 0));}/* * udp_send:	send an UDP packet */intudp_send(int fd, char *msg, int mlen, void *addr, int addrlen){	return (sendto(fd, msg, mlen, 0, (struct sockaddr *) addr, addrlen));}/* * resolv_domain: get a domain for a name, used to get local domain * */intresolv_domain(char *buf, int buflen, char *host){	struct	sockaddr	*sa;	socklen_t		salen;	if ((sa = resolv_name(host, NULL, NULL, &salen)) == NULL ||	    resolv_addr(sa, salen, buf, buflen, NULL, 0) == -1) {		*buf = '\0';	}	return (1);}

⌨️ 快捷键说明

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