#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <rpc/rpc.h>
#include <errno.h>

main() {

	int err, ret, sockfd;
	struct sockaddr_in myaddr;

	printf("prepare\n");

	errno = 0;
	if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1) {
		printf("socket returned error %d", errno);
		exit(1);
	}

	printf("bindresvport to valid port/family\n");
	myaddr.sin_family=AF_INET;
	/* port is 22, which is in the reserved port range */ 
	myaddr.sin_port=htons(22);
	myaddr.sin_addr.s_addr=htonl(0x7F000001);

	errno = 0;
	if ((ret=bindresvport(sockfd, &myaddr)) == -1) {
	        err = errno;
	        printf("bindresvport 1 FAIL");
	        if (err != 0) {
	            printf(", errno was set to %d", err);
	        }
	        printf("\n");
	} else
		printf("Success, bound to port %d\n", ntohs(myaddr.sin_port));


	printf("bindresvport to anonymous port/valid family\n");
	myaddr.sin_family=AF_INET;
	/* port is 0, which means auto-allocate */
	myaddr.sin_port=htons(0);
	myaddr.sin_addr.s_addr=htonl(0x7F000001);

	errno = 0;
	if ((ret=bindresvport(sockfd, &myaddr)) == -1) {
	        err = errno;
	        printf("bindresvport 2 FAIL");
	        if (err != 0) {
	            printf(", errno was set to %d", err);
	        }
	        printf("\n");
	} else
        if (ntohs(myaddr.sin_port) < 600 || ntohs(myaddr.sin_port) > 1023) {
		printf ("binresvport returned invalid port %d, expecting 600-1023\n", ntohs(myaddr.sin_port));
	} else
		printf("Success, bound to port %d\n", ntohs(myaddr.sin_port));


	printf("bindresvport with NULL sockaddr_in\n");
	errno = 0;
	if ((ret=bindresvport(sockfd, NULL)) == -1) {
	        err = errno;
	        printf("bindresvport 3 FAIL");
	        if (err != 0) {
	            printf(", errno was set to %d", err);
	        }
	        printf("\n");
	} else
		/* can't tell what port we got back, so can't check range */
		printf("Success\n");


	printf("bindresvport to valid port, invalid family\n");
    	myaddr.sin_family=AF_INET6;
	/* port is 22, which is reserved port */ 
	myaddr.sin_port=htons(22);
	myaddr.sin_addr.s_addr=htonl(0x7F000001);

	errno = 0;
	if ((ret=bindresvport(sockfd, &myaddr)) != -1) {
    		printf("bindresvport 4 FAIL\n");
		printf("bound to port %d\n", ntohs(myaddr.sin_port));
    	}
    	else {
    		err = errno;
        	if (err != EPFNOSUPPORT && err != EAFNOSUPPORT) {
			printf("errno was set to %d, expecting EPFNOSUPPORT(96) or EAFNOSUPPORT(97)\n", err);
        	} else
			printf ("Success\n");
	}


	printf("bindresvport to invalid port, valid family\n");
	myaddr.sin_family=AF_INET;
	/* port is 2222, which is outside the reserved range */ 
	myaddr.sin_port=htons(2222);
	myaddr.sin_addr.s_addr=htonl(0x7F000001);

	errno = 0;
	if ((ret=bindresvport(sockfd, &myaddr)) != -1) {
    		printf("bindresvport 5 FAIL\n");
		printf("bound to port %d\n", ntohs(myaddr.sin_port));
    	}
    	else {
    		err = errno;
        	if (err != EINVAL) {
			printf("errno was set to %d, expecting EINVAL(22)\n", err);
        	} else
			printf ("Success\n");
	}

        printf ("Done.\n");

	close(sockfd);
}
