Exemple #1
0
int main(int argc, char **argv)
{
        int opt;
        int flag_description = 0;
        const char *address;

        opt = getopt(argc, argv, "d");
        if (opt == 'd')
        {
                argc--;
                argv++;
                flag_description = 1;
        }
        else if (opt != -1)
        {
                printf("\nUNKNOWN OPTION: -%c.\n\n", opt);
                print_syntax();
                return 1;
        }

        address = (argc == 1) ? NULL : argv[1];
        print_addr_info(address, flag_description);
        printf("\n");
        
        return 0;
}
Exemple #2
0
static int deal(int fd, fd_set *socket_fd_set)
{
	int client_socket_fd;
	struct sockaddr_in client_address;
	int client_addr_len;

	if (socket_fd_set == NULL)
		return 0;

	if (fd == socket_fd) {
		client_addr_len = sizeof(client_address);

		client_socket_fd = accept(socket_fd, (struct sockaddr*)&client_address, (socklen_t*)&client_addr_len);
		if (client_socket_fd != -1) {
			FD_SET(client_socket_fd, socket_fd_set);
			
			#ifdef DEBUG
			printf("A client connect.\n");
			print_addr_info(client_address);
			#endif
		}
	}
	else {
		if (!echo(fd)) {
			close(fd);
			FD_CLR(fd, socket_fd_set);
			
			#ifdef DEBUG
			printf("A client disconnect.\n");
			#endif
		}
	}

	return 1;
}
int main(int argc, char **argv)
{
	int opt, sock, newsock, result, flags, if_index = 0, on = 1;
	socklen_t sinlen, opt_len;
	struct sockaddr_storage sin;
	struct addrinfo hints, *res;
	struct sctp_sndrcvinfo sinfo;
	struct pollfd poll_fd;
	char getsockopt_peerlabel[1024];
	char byte, *peerlabel, msglabel[1024], if_name[30];
	bool nopeer = false,  verbose = false,  ipv4 = false, snd_opt = false;
	char *context, *host_addr = NULL, *bindx_addr = NULL;
	struct sockaddr_in ipv4_addr;
	unsigned short port;

	while ((opt = getopt(argc, argv, "4b:h:inv")) != -1) {
		switch (opt) {
		case '4':
			ipv4 = true;
			break;
		case 'b':
			bindx_addr = optarg;
			break;
		case 'h':
			host_addr = optarg;
			break;
		case 'i':
			snd_opt = true;
			break;
		case 'n':
			nopeer = true;
			break;
		case 'v':
			verbose = true;
			break;
		default:
			usage(argv[0]);
		}
	}

	if ((argc - optind) != 2)
		usage(argv[0]);

	port = atoi(argv[optind + 1]);
	if (!port)
		usage(argv[0]);

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_flags = AI_PASSIVE;
	hints.ai_protocol = IPPROTO_SCTP;

	if (ipv4)
		hints.ai_family = AF_INET;
	else
		hints.ai_family = AF_INET6;

	if (!strcmp(argv[optind], "stream"))
		hints.ai_socktype = SOCK_STREAM;
	else if (!strcmp(argv[optind], "seq"))
		hints.ai_socktype = SOCK_SEQPACKET;
	else
		usage(argv[0]);

	if (verbose) {
		if (getcon(&context) < 0)
			context = strdup("unavailable");
		printf("Server process context: %s\n", context);
		free(context);
	}

	if (host_addr) {
		char *ptr;

		ptr = strpbrk(host_addr, "%");
		if (ptr)
			strcpy(if_name, ptr + 1);

		if_index = if_nametoindex(if_name);
		if (!if_index) {
			perror("Server if_nametoindex");
			exit(1);
		}

		result = getaddrinfo(host_addr, argv[optind + 1],
				     &hints, &res);

	} else {
		result = getaddrinfo(NULL, argv[optind + 1], &hints, &res);
	}

	if (result < 0) {
		fprintf(stderr, "Server getaddrinfo: %s\n",
			gai_strerror(result));
		exit(1);
	}

	sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (sock < 0) {
		perror("Server socket");
		exit(1);
	}

	result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	if (result < 0) {
		perror("Server setsockopt: SO_REUSEADDR");
		close(sock);
		exit(1);
	}

	/* Enables sctp_data_io_events for sctp_recvmsg(3) for assoc_id. */
	result = setsockopt(sock, SOL_SCTP, SCTP_EVENTS, &on, sizeof(on));
	if (result < 0) {
		perror("Server setsockopt: SCTP_EVENTS");
		close(sock);
		exit(1);
	}

	if (bindx_addr) {
		memset(&ipv4_addr, 0, sizeof(struct sockaddr_in));
		ipv4_addr.sin_family = AF_INET;
		ipv4_addr.sin_port = htons(port);
		ipv4_addr.sin_addr.s_addr = inet_addr(bindx_addr);

		result = sctp_bindx(sock, (struct sockaddr *)&ipv4_addr, 1,
				    SCTP_BINDX_ADD_ADDR);
		if (result < 0) {
			perror("Server sctp_bindx ADD - ipv4");
			close(sock);
			exit(1);
		}
	} else {
		result = bind(sock, res->ai_addr, res->ai_addrlen);
		if (result < 0) {
			perror("Server bind");
			close(sock);
			exit(1);
		}
	}

	if (verbose) {
		print_context(sock, "Server LISTEN");
		print_ip_option(sock, ipv4, "Server LISTEN");
	}

	if (listen(sock, SOMAXCONN)) {
		perror("Server listen");
		close(sock);
		exit(1);
	}

	if (hints.ai_socktype == SOCK_STREAM) {
		if (verbose)
			print_context(sock, "Server STREAM");

		do {
			socklen_t labellen = sizeof(getsockopt_peerlabel);

			sinlen = sizeof(sin);

			newsock = accept(sock, (struct sockaddr *)&sin,
					 &sinlen);
			if (newsock < 0) {
				perror("Server accept");
				close(sock);
				exit(1);
			}

			if (verbose) {
				print_context(newsock,
					      "Server STREAM accept on newsock");
				print_addr_info((struct sockaddr *)&sin,
						"Server connected to Client");
				print_ip_option(newsock, ipv4,
						"Server STREAM accept on newsock");
			}

			if (nopeer) {
				peerlabel = strdup("nopeer");
			} else if (snd_opt) {
				peerlabel = get_ip_option(newsock, ipv4,
							  &opt_len);
				if (!peerlabel)
					peerlabel = strdup("no_ip_options");
			} else {
				result = getpeercon(newsock, &peerlabel);
				if (result < 0) {
					perror("Server getpeercon");
					close(sock);
					close(newsock);
					exit(1);
				}

				/* Also test the getsockopt version */
				result = getsockopt(newsock, SOL_SOCKET,
						    SO_PEERSEC,
						    getsockopt_peerlabel,
						    &labellen);
				if (result < 0) {
					perror("Server getsockopt: SO_PEERSEC");
					close(sock);
					close(newsock);
					exit(1);
				}
				if (verbose)
					printf("Server STREAM SO_PEERSEC peer label: %s\n",
					       getsockopt_peerlabel);
			}
			printf("Server STREAM %s: %s\n",
			       snd_opt ? "sock_opt" : "peer label", peerlabel);

			result = read(newsock, &byte, 1);
			if (result < 0) {
				perror("Server read");
				close(sock);
				close(newsock);
				exit(1);
			}

			result = write(newsock, peerlabel, strlen(peerlabel));
			if (result < 0) {
				perror("Server write");
				close(sock);
				close(newsock);
				exit(1);
			}

			if (verbose)
				printf("Server STREAM sent: %s\n", peerlabel);

			free(peerlabel);

			/* Let the client close the connection first as this
			 * will stop OOTB chunks if newsock closed early.
			 */
			poll_fd.fd = newsock;
			poll_fd.events = POLLRDHUP;
			poll_fd.revents = 1;
			result = poll(&poll_fd, 1, 1000);
			if (verbose && result == 1)
				printf("Server STREAM: Client closed connection\n");
			else if (verbose && result == 0)
				printf("Server: poll(2) timed out - OKAY\n");
			else if (result < 0)
				perror("Server - poll");

			close(newsock);
		} while (1);
	} else { /* hints.ai_socktype == SOCK_SEQPACKET */
		if (verbose)
			print_context(sock, "Server SEQPACKET sock");

		do {
			sinlen = sizeof(sin);

			result = sctp_recvmsg(sock, msglabel, sizeof(msglabel),
					      (struct sockaddr *)&sin, &sinlen,
					      &sinfo, &flags);
			if (result < 0) {
				perror("Server sctp_recvmsg");
				close(sock);
				exit(1);
			}

			if (verbose) {
				print_context(sock, "Server SEQPACKET recvmsg");
				print_addr_info((struct sockaddr *)&sin,
						"Server SEQPACKET recvmsg");
				print_ip_option(sock, ipv4,
						"Server SEQPACKET recvmsg");
			}

			if (nopeer) {
				peerlabel = strdup("nopeer");
			} else if (snd_opt) {
				peerlabel = get_ip_option(sock, ipv4, &opt_len);

				if (!peerlabel)
					peerlabel = strdup("no_ip_options");
			} else {
				result = getpeercon(sock, &peerlabel);
				if (result < 0) {
					perror("Server getpeercon");
					close(sock);
					exit(1);
				}
			}
			printf("Server SEQPACKET %s: %s\n",
			       snd_opt ? "sock_opt" : "peer label", peerlabel);

			if (sin.ss_family == AF_INET6 && host_addr)
				((struct sockaddr_in6 *)&sin)->sin6_scope_id = if_index;

			result = sctp_sendmsg(sock, peerlabel,
					      strlen(peerlabel),
					      (struct sockaddr *)&sin,
					      sinlen, 0, 0, 0, 0, 0);
			if (result < 0) {
				perror("Server sctp_sendmsg");
				close(sock);
				exit(1);
			}

			if (verbose)
				printf("Server SEQPACKET sent: %s\n",
				       peerlabel);

			free(peerlabel);
		} while (1);
	}

	close(sock);
	exit(0);
}