/* A test program that prints out what the machines preferred options
 * when getaddrinfo gets free hands.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(int argc, char *argv[])
{
	int listenfd, err;
	struct addrinfo hints, *res, *curr;
	char *host = NULL, *serv = "12345";

	if (argc > 1)
		host = argv[1];
	if (argc > 2)
		serv = argv[2];

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

	err = getaddrinfo(host, serv, &hints, &res);
	if (err) {
		fprintf(stderr, "ERROR: getaddrinfo() failed: %s\n",
				gai_strerror(err));
		return -1;
	}

#if 1
	printf("When given unspecified protocol, host:%s and port:%s, as hints...\n", host, serv);

	printf("This machine prefers listening on (in order of preference):\n");
	for (curr = res; curr != NULL; curr = curr->ai_next) {
		listenfd = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
		if (listenfd < 0)
			continue;

		
		switch (curr->ai_family) {
		case AF_INET6:
		{
			int v6only;
			socklen_t len = sizeof(v6only);
			getsockopt(listenfd, IPPROTO_IPV6, IPV6_V6ONLY,
					&v6only, &len);
			if (v6only)
				printf("\t* ipv6 (only)\n");
			else
				printf("\t* ipv6+ipv4\n");
			break;
		}
		case AF_INET:
			printf("\t* ipv4 (only)\n");
			break;
		default:
			printf("\t* other protocol\n");
			break;
		}

#else /* usually you'd do something like this */
		/* make sure IPV6_V6ONLY is off (Linux default) */
		if (curr->ai_family == AF_INET6) {
			int off = 0;

			setsockopt(listenfd, IPPROTO_IPV6, IPV6_V6ONLY,
					&off, sizeof(off));

		}

		err = bind(listenfd, curr->ai_addr, curr->ai_addrlen);
		if (err) {
			close(listenfd);
			continue;
		}

		err = listen(listenfd, 5);
		if (err) {
			close(listenfd);
			continue;
		}

		/* listening socket successfully created! */
		break;
#endif
	}

	if (curr == NULL) {
		listenfd = -2;
	}

	freeaddrinfo(res);

	return 0;
}

