示例#1
0
int makesock(char* host, char* port,char server) {
	int sfd = 0;
	struct addrinfo hints;
	struct addrinfo *addr;
	memset(&hints,0,sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_ADDRCONFIG;
	if (server == 1) {
		hints.ai_flags = hints.ai_flags | AI_PASSIVE;
	}
	int gai = getaddrinfo(host,port,&hints,&addr);
	if (gai != 0) {
		printf("getaddrinfo error\n");
		printf(gai_strerror(gai));
	}
	/* borrow socket check from libsocket */
	struct addrinfo *check;
	for (check = addr; check != NULL; check = check->ai_next) {
		sfd = socket(check->ai_family,check->ai_socktype,check->ai_protocol);
		if (sfd < 0) continue;
		if (server == 1) {
			if (-1 != bind(sfd,check->ai_addr,check->ai_addrlen)) {
				printf("Listening\n");
				setupsock(sfd);
				break;
			}
		}
		else if (server == 0) {
			if (-1 != connect(sfd,check->ai_addr,check->ai_addrlen)) {
				printf("Connected");
				setupsock(sfd);
				break;
			}
		}
	}
	if (addr != NULL) freeaddrinfo(addr);
	return(sfd);
}
示例#2
0
文件: nfsd.c 项目: ryo/netbsd-src
/*
 * Nfs server daemon mostly just a user context for nfssvc()
 *
 * 1 - do file descriptor and signal cleanup
 * 2 - create the nfsd thread(s)
 * 3 - create server socket(s)
 * 4 - register socket with portmap
 *
 * For connectionless protocols, just pass the socket into the kernel via
 * nfssvc().
 * For connection based sockets, loop doing accepts. When you get a new
 * socket from accept, pass the msgsock into the kernel via nfssvc().
 * The arguments are:
 *	-r - reregister with portmapper
 *	-t - support only tcp nfs clients
 *	-u - support only udp nfs clients
 *	-n num how many threads to create.
 *	-4 - use only ipv4
 *	-6 - use only ipv6
 */
int
main(int argc, char *argv[])
{
	struct conf cfg[4];
	struct pollfd set[__arraycount(cfg)];
	int ch, connect_type_cnt;
	size_t i, nfsdcnt;
	int reregister;
	int tcpflag, udpflag;
	int ip6flag, ip4flag;
	int s, compat;
	int parent_fd = -1;
	pthread_t *workers;

#define	DEFNFSDCNT	 4
	nfsdcnt = DEFNFSDCNT;
	compat = reregister = 0;
	tcpflag = udpflag = 1;
	ip6flag = ip4flag = 1;
#define	GETOPT	"46dn:rtu"
#define	USAGE	"[-46drtu] [-n num_servers]"
	while ((ch = getopt(argc, argv, GETOPT)) != -1) {
		switch (ch) {
		case '6':
			ip6flag = 1;
			ip4flag = 0;
			s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
			if (s < 0 && (errno == EPROTONOSUPPORT ||
			    errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
				ip6flag = 0;
			else
				close(s);
			break;
		case '4':
			ip6flag = 0;
			ip4flag = 1;
			s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
			if (s < 0 && (errno == EPROTONOSUPPORT ||
			    errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
				ip4flag = 0;
			else
				close(s);
			break;
		case 'd':
			debug++;
			break;
		case 'n':
			nfsdcnt = atoi(optarg);
			if (nfsdcnt < 1) {
				warnx("nfsd count %zu; reset to %d", nfsdcnt,
				    DEFNFSDCNT);
				nfsdcnt = DEFNFSDCNT;
			}
			break;
		case 'r':
			reregister = 1;
			break;
		case 't':
			compat |= 2;
			tcpflag = 1;
			udpflag = 0;
			break;
		case 'u':
			compat |= 1;
			tcpflag = 0;
			udpflag = 1;
			break;
		default:
		case '?':
			usage();
		}
	}
	argv += optind;
	argc -= optind;

	if (compat == 3) {
		warnx("Old -tu options detected; enabling both udp and tcp.");
		warnx("This is the default behavior now and you can remove");
		warnx("all options.");
		tcpflag = udpflag = 1;
		if (ip6flag == 1 && ip4flag == 0)
			ip4flag = 1;
	}

	if (debug == 0) {
		parent_fd = daemon2_fork();
		if (parent_fd == -1)
			logit(LOG_ERR, "daemon2_fork failed");
		openlog("nfsd", LOG_PID, LOG_DAEMON);
	}


	memset(cfg, 0, sizeof(cfg));
	for (i = 0; i < __arraycount(cfg); i++) {
		if (ip4flag == 0 && cfg_family[i] == PF_INET)
			continue;
		if (ip6flag == 0 && cfg_family[i] == PF_INET6)
			continue;
		if (tcpflag == 0 && cfg_protocol[i] == IPPROTO_TCP)
			continue;
		if (udpflag == 0 && cfg_protocol[i] == IPPROTO_UDP)
			continue;
		tryconf(&cfg[i], i, reregister);
	}

	workers = calloc(nfsdcnt, sizeof(*workers));
	if (workers == NULL) {
		logit(LOG_ERR, "thread alloc %s", strerror(errno));
		exit(1);
	}

	for (i = 0; i < nfsdcnt; i++) {
		int error;

		error = pthread_create(&workers[i], NULL, worker, NULL);
		if (error) {
			errno = error;
			logit(LOG_ERR, "pthread_create: %s", strerror(errno));
			exit(1);
		}
	}

	connect_type_cnt = 0;
	for (i = 0; i < __arraycount(cfg); i++) {
		set[i].fd = -1;
		set[i].events = POLLIN;
		set[i].revents = 0;

		if (cfg[i].nc == NULL)
			continue;

		setupsock(&cfg[i], &set[i], i);
		if (set[i].fd != -1)
			connect_type_cnt++;

	}

	pthread_setname_np(pthread_self(), "master", NULL);

	if (debug == 0) {
		daemon2_detach(parent_fd, 0, 0);
		(void)signal(SIGHUP, SIG_IGN);
		(void)signal(SIGINT, SIG_IGN);
		(void)signal(SIGQUIT, SIG_IGN);
		(void)signal(SIGSYS, nonfs);
	}

	if (connect_type_cnt == 0) {
		for (i = 0; i < nfsdcnt; i++)
			    pthread_join(workers[i], NULL);
		exit(0);
	}

	/*
	 * Loop forever accepting connections and passing the sockets
	 * into the kernel for the mounts.
	 */
	for (;;) {
		if (poll(set, __arraycount(set), INFTIM) == -1) {
			logit(LOG_ERR, "poll failed: %s", strerror(errno));
			exit(1);
		}

		for (i = 0; i < __arraycount(set); i++) {
			struct nfsd_args nfsdargs;
			struct sockaddr_storage ss;
			socklen_t len;
			int msgsock;
			int on = 1;

			if ((set[i].revents & POLLIN) == 0)
				continue;
			len = sizeof(ss);
			if ((msgsock = accept(set[i].fd,
			    (struct sockaddr *)&ss, &len)) == -1) {
				int serrno = errno;
				logit(LOG_ERR, "accept failed: %s",
				    strerror(errno));
				if (serrno == EINTR || serrno == ECONNABORTED)
					continue;
				exit(1);
			}
			if (setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, &on,
			    sizeof(on)) == -1)
				logit(LOG_ERR, "setsockopt SO_KEEPALIVE: %s",
				    strerror(errno));
			nfsdargs.sock = msgsock;
			nfsdargs.name = (void *)&ss;
			nfsdargs.namelen = len;
			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
			(void)close(msgsock);
		}
	}
}