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

📄 netutils.c

📁 一套客户/服务器模式的备份系统代码,跨平台,支持linux,AIX, IRIX, FreeBSD, Digital Unix (OSF1), Solaris and HP-UX.
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************** Start of $RCSfile: netutils.c,v $  ****************** $Source: /home/alb/afbackup/afbackup-3.3.8.1/RCS/netutils.c,v $* $Id: netutils.c,v 1.6 2005/01/15 08:54:32 alb Exp alb $* $Date: 2005/01/15 08:54:32 $* $Author: alb $********* description *********************************************************************************************************************/#include <conf.h>#include <version.h>  static char * fileversion = "$RCSfile: netutils.c,v $ $Source: /home/alb/afbackup/afbackup-3.3.8.1/RCS/netutils.c,v $ $Id: netutils.c,v 1.6 2005/01/15 08:54:32 alb Exp alb $ " PACKAGE " " VERSION_STRING;#include <stdio.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <sys/utsname.h>#include <sys/types.h>#include <sys/socket.h>#include <signal.h>#ifdef	HAVE_SYS_TIME_H#include <sys/time.h>#endif#include <netinet/in.h>#include <netdb.h>#ifdef	HAVE_NETINET_IN_SYSTM_H#include <netinet/in_systm.h>#endif#ifdef	HAVE_NETINET_IP_H#include <netinet/ip.h>#endif#ifdef	HAVE_NETINET_TCP_H#include <netinet/tcp.h>#endif#ifdef	HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#include <x_types.h>#include <sysutils.h>#include <netutils.h>#include <fileutil.h>#include <genutils.h>#ifdef	HAVE_SYS_SELECT_H#include <sys/select.h>#endif#define	CLEANUPR(ret)	{ r = (ret); goto cleanup; }#define	CLEANUP		{ goto cleanup; }#define	GETOUT		{ goto getout; }#define	EMPTY_USER_DATA	((void *) 1)typedef struct _tcpmux_status {  int		listensock;  int		unixsock;  Int32		maxconn;  Int32		num_conns;  void		**conn_user_data;  int		*conns;  FILE		**conn_fps;  fd_set	allfds;  int		maxfd;  Flag		*closed_conns;  Flag		have_closed_conns;  void		(*failed_conn_func)(int, void *, void *);  void		*(*conn_init_func)(int, Int32, void *, struct sockaddr *,				void *, TcpMuxCallbDoneActions *);  void		*data;  Uns32		flags;  void		*conn_user_data_to_be_freed;} TcpMuxStatus;struct hostent *get_host_by_name(UChar * name){#if	defined(HAVE_GETIPNODEBYNAME) && defined(HAVE_IP6)  int		error_num;  struct hostent	*he;	/* None of the flags (arg 3) does, what i consider appropriate. */	/* i guess, most of the networks will move from IP4 to IP6, thus */	/* introduce new IP6 nodes, that should be able to communicate */	/* with old and existing IP4 nodes. If there are new IP6 nodes, */	/* having also a IP4 address, the latter one can happily be used. */	/* If others should use IP6 to communicate with the host, that */	/* still has also an IP4 entry, the administrator should gefaelligst */	/* delete the IP4 entry, because then it makes no sense any more. */	/* Thus i implement it explicitely requiring 2 lookups :-( */  he = getipnodebyname(name, AF_INET, 0, &error_num);  if(!he){    he = getipnodebyname(name, AF_INET6, 0, &error_num);    errno = error_num;  }  return(he);#else  return(gethostbyname(name));#endif}struct hostent *get_host_by_addr(void * addr, int len, int type){#if	defined(HAVE_GETIPNODEBYADDR) && defined(HAVE_IP6)  int		error_num;  struct hostent	*he;  he = getipnodebyaddr(addr, len, type, &error_num);  if(!he)    errno = error_num;  return(he);#else  return(gethostbyaddr(addr, len, type));#endif}struct hostent *get_host_by_sockaddr(struct sockaddr * addr){  if(((struct sockaddr *)addr)->sa_family == AF_INET)    return(get_host_by_addr(&(((struct sockaddr_in *)addr)->sin_addr),			sizeof(struct in_addr), AF_INET));#ifdef	HAVE_IP6  if(((struct sockaddr *)addr)->sa_family == AF_INET6)    return(get_host_by_addr(&(((struct sockaddr_in6 *)addr)->sin6_addr),			sizeof(struct in6_addr), AF_INET6));#endif  return(NULL);}static Flagaccept_connection(TcpMuxStatus * status, Flag in_subr, Flag uxsock){  int		fl, fd, sock;  Flag		end = NO;  Int32		sock_optlen[2];#define	addr_len sock_optlen  nodeaddr	peeraddr;  TcpMuxCallbDoneActions	init_done_actions;  sock = (uxsock ? status->unixsock : status->listensock);  fl = fcntl(sock, F_GETFL);  fcntl(sock, F_SETFL, fl | NONBLOCKING_FLAGS);  *((int *) &(addr_len[0])) = sizeof(peeraddr);  fd = accept(sock, (struct sockaddr *)(&peeraddr), (int *) &(addr_len[0]));  if(fd < 0 || (status->maxconn > 0 && status->num_conns + 1 > status->maxconn)){    if(status->failed_conn_func)	status->failed_conn_func(fd >= 0 ? fd : sock, status->data, status);    if(fd >= 0)	close(fd);  }  else{    fcntl(sock, F_SETFL, fl & INV_NONBLOCKING_FLAGS);    fl = fcntl(fd, F_GETFL);    fcntl(fd, F_SETFL, fl & INV_NONBLOCKING_FLAGS);    fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | 1);    if(in_subr && ! status->conn_user_data_to_be_freed){		/* the memory space must be valid until exit from input_proc_func, */		/* cause it might be in use by that function, so we store it in a */		/* status field and free it later */	status->conn_user_data_to_be_freed = status->conn_user_data;	status->conn_user_data = NEWP(void *, status->num_conns + 2);	memcpy(status->conn_user_data, status->conn_user_data_to_be_freed,			sizeof(void *) * (status->num_conns + 1));    }    else{	status->conn_user_data = ZRENEWP(status->conn_user_data, void *, status->num_conns + 2);    }    status->conns = ZRENEWP(status->conns, int, status->num_conns + 1);    status->closed_conns = ZRENEWP(status->closed_conns, Flag, status->num_conns + 1);    status->conn_fps = ZRENEWP(status->conn_fps, FILE *, status->num_conns + 1);    status->closed_conns[status->num_conns] = NO;    status->conn_user_data[status->num_conns + 1] = NULL;    if(status->conn_init_func){	SETZERO(init_done_actions);	init_done_actions.conns_to_close = status->closed_conns;	status->conn_user_data[status->num_conns] = (*status->conn_init_func)(fd,			status->num_conns, &status->conn_user_data,			(struct sockaddr *)(&peeraddr), status->data,			&init_done_actions);	if(!status->conn_user_data[status->num_conns]){	  close(fd);	  fd = -1;	  if(status->num_conns < 1 && (status->flags & TCPMUX_STOP_ON_LAST_CLOSE))	    end = YES;	}	if(init_done_actions.have_conns_to_close)	  status->have_closed_conns = YES;    }    else      status->conn_user_data[status->num_conns] = EMPTY_USER_DATA;    if(fd >= 0){	set_socket_keepalive(fd);	status->conns[status->num_conns] = fd;	status->conn_fps[status->num_conns] = fdopen(fd, "r+");	FD_SET(fd, &status->allfds);	if(fd > status->maxfd)	  status->maxfd = fd;	status->num_conns++;    }  }  return(end);}Int32tcp_mux_long_io(  void *	tmstatptr,  int		fd,  UChar *	data,  Int32		num,  Int32		do_write,  Int32		(*rw_func)(int, UChar *, Int32)){  fd_set	rfds, wfds;  int		sock, uxsock;  Int32		i, n;  TcpMuxStatus	*tcpmux_status;  Flag		lastconn;  if(!tmstatptr)    return((*rw_func)(fd, data, num));  tcpmux_status = (TcpMuxStatus *) tmstatptr;  sock = tcpmux_status->listensock;  uxsock = tcpmux_status->unixsock;  n = MAX(fd, sock) + 1;  forever{    FD_ZERO(&rfds);    FD_ZERO(&wfds);    if(sock >= 0)	FD_SET(sock, &rfds);    if(uxsock >= 0)	FD_SET(uxsock, &rfds);    FD_SET(fd, (do_write ? (&wfds) : (&rfds)));    i = select(n, &rfds, &wfds, NULL, NULL);    if(i <= 0)	return(i);    if(FD_ISSET(fd, (do_write ? (&wfds) : (&rfds))))	return((*rw_func)(fd, data, num));    lastconn = NO;    if(sock >= 0)      if(FD_ISSET(sock, &rfds))	lastconn = (lastconn || accept_connection(tmstatptr, YES, NO));    if(uxsock >= 0)      if(FD_ISSET(uxsock, &rfds))	lastconn = (lastconn || accept_connection(tmstatptr, YES, YES));    if(lastconn)	fprintf(stderr, "Internal error in netutils.c, 1.\n");  }}Int32tcp_mux_service(  int		port,  UChar		*ux_socket,  void		*(*conn_init_func)(int, Int32, void *, struct sockaddr *, void *, TcpMuxCallbDoneActions *),  Int32		(*input_proc_func)(int, void *, Int32, void *, TcpMuxCallbDoneActions *, void *),  Int32		(*conn_deinit_func)(int, void *, Int32, void *, void *),  Int32		maxconn,  void		(*failed_conn_func)(int, void *, void *),  Uns32		flags,  void		*data){  Int32		i, j;  Int32		r = 0;  Int32		actconn;  nodeaddr	addr;  int		sock_optval, sockfd_socktype;  int		sock_typesize, sock_family;  Int32		sock_optlen[2];  Flag		end = NO;  fd_set	tmpfds;  TcpMuxStatus	status;  TcpMuxCallbDoneActions	input_done_actions;  struct sigaction	pipe_sigact, org_sigact;  SETZERO(status);  status.maxconn = maxconn;  status.failed_conn_func = failed_conn_func;  status.conn_init_func = conn_init_func;  status.data = data;  status.flags = flags;  status.listensock = -1;  status.unixsock = -1;  SETZERO(pipe_sigact);  pipe_sigact.sa_handler = SIG_IGN;#ifdef	SA_RESTART  pipe_sigact.sa_flags = SA_RESTART;#endif  sigaction(SIGPIPE, &pipe_sigact, &org_sigact);  if(flags & TCPMUX_INETD_STARTED){    status.listensock = 0;  }  else{#ifdef	HAVE_IP6    status.listensock = socket(sock_family = AF_INET6, SOCK_STREAM, 0);    if(status.listensock < 0)#endif     status.listensock = socket(sock_family = AF_INET, SOCK_STREAM, 0);    if(status.listensock >= 0){	*((int *) &(sock_optlen[0])) = sizeof(int);	i = getsockopt(status.listensock, SOL_SOCKET, SO_TYPE,			(char *) &sockfd_socktype, (int *) &(sock_optlen[0]));	if(i)	  sockfd_socktype = -1;	sock_optval = 1;	if(sockfd_socktype == SOCK_STREAM){	  i = setsockopt(status.listensock, SOL_SOCKET, SO_REUSEADDR,				(char *) &sock_optval, sizeof(int));	  /* i is not evaluated: if set REUSEADDR fails, the bind		below fails. That's sufficient */	}#ifdef	HAVE_IP6	i = -1;	if(sock_family == AF_INET6){	  ((struct sockaddr *)(&addr))->sa_family = AF_INET6;	  ((struct sockaddr_in6 *)(&addr))->sin6_port = htons(port);	  SETZERO(((struct sockaddr_in6 *)(&addr))->sin6_addr.s6_addr);	  sock_typesize = sizeof(struct sockaddr_in6);	  i = bind(status.listensock, (struct sockaddr *)(&addr), sock_typesize);	}	if(i){#endif	((struct sockaddr *)(&addr))->sa_family = AF_INET;	((struct sockaddr_in *)(&addr))->sin_port = htons(port);	SETZERO(((struct sockaddr_in *)(&addr))->sin_addr.s_addr);	sock_typesize = sizeof(struct sockaddr_in);	if( (i = bind(status.listensock, (struct sockaddr *)(&addr), sock_typesize)) ){	  close(status.listensock);	  status.listensock = -1;	}    #ifdef	HAVE_IP6	}#endif	if(!i){	  if(listen(status.listensock, 64)){	    close(status.listensock);	    status.listensock = -1;	  }	}    }  }  if(ux_socket){    status.unixsock = create_unix_socket(ux_socket);    if(status.unixsock >= 0){	fcntl(status.unixsock, F_SETFD, fcntl(status.unixsock, F_GETFD) | 1);	i = listen(status.unixsock, 64);	if(i){	  close(status.unixsock);	  status.unixsock = -1;	}    }  }  if(status.listensock < 0 && status.unixsock < 0)    CLEANUPR(-1);  if(status.listensock >= 0)    fcntl(status.listensock, F_SETFD, fcntl(status.listensock, F_GETFD) | 1);  FD_ZERO(&status.allfds);  if(status.listensock >= 0)    FD_SET(status.listensock, &status.allfds);  if(status.unixsock >= 0)    FD_SET(status.unixsock, &status.allfds);  status.maxfd = MAX(status.listensock, status.unixsock);  actconn = status.num_conns;	/* force accept first */  do{    status.have_closed_conns = NO;    COPYVAL(tmpfds, status.allfds);    i = select(status.maxfd + 1, &tmpfds, NULL, NULL, 0);    memset(status.closed_conns, 0, status.num_conns * sizeof(status.closed_conns[0]));    for(i = -1; i < status.num_conns; i++){	/* one more because of */	if(actconn >= status.num_conns){	/* rotating accept and */	  if(status.listensock >= 0){	    if(FD_ISSET(status.listensock, &tmpfds)){	/* continue */	      if(accept_connection(&status, NO, NO))		end = YES;	    }	  }	  if(status.unixsock >= 0){	    if(FD_ISSET(status.unixsock, &tmpfds)){	/* continue */	      if(accept_connection(&status, NO, YES))		end = YES;	    }	  }	  actconn = 0;	  continue;	}	if(FD_ISSET(status.conns[actconn], &tmpfds)){	  if(input_proc_func){	    SETZERO(input_done_actions);	    input_done_actions.conns_to_close = status.closed_conns;	    j = (*input_proc_func)(status.conns[actconn],				status.conn_user_data + actconn, actconn, data,				&input_done_actions, &status);	    if(j)		status.closed_conns[actconn] = status.have_closed_conns = YES;	    ZFREE(status.conn_user_data_to_be_freed);	    if(input_done_actions.have_conns_to_close)		status.have_closed_conns = YES;	  }	}	actconn++;    }    if(status.have_closed_conns){      for(i = 0; i < status.num_conns; i++){	if(status.closed_conns[i]){	  if(conn_deinit_func){	    j = (*conn_deinit_func)(status.conns[i], status.conn_user_data + i, i,					data, &status);	  }	  FD_CLR(status.conns[i], &status.allfds);	  if(status.conn_fps[i])	    fclose(status.conn_fps[i]);	  else	    close(status.conns[i]);	  if(status.conns[i] == status.maxfd)	    status.maxfd--;	  memmove(status.conns + i, status.conns + i + 1,			(status.num_conns - i - 1) * sizeof(status.conns[0]));	  memmove(status.conn_fps + i, status.conn_fps + i + 1,			(status.num_conns - i - 1) * sizeof(status.conn_fps[0]));	  memmove(status.closed_conns + i, status.closed_conns + i + 1,			(status.num_conns - i - 1) * sizeof(status.closed_conns[0]));	  memmove(status.conn_user_data + i, status.conn_user_data + i + 1,			(status.num_conns - i) * sizeof(status.conn_user_data[0]));	  i--;	  status.num_conns--;	  if(status.num_conns < 1 && (flags & TCPMUX_STOP_ON_LAST_CLOSE)){	    end = YES;	    break;	  }	}      }    }  } while(! end); cleanup:  if(status.listensock >= 0)    close(status.listensock);  if(status.unixsock >= 0)    close(status.unixsock);  ZFREE(status.conns);  ZFREE(status.conn_fps);

⌨️ 快捷键说明

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