/* Allocate a privileged port that is not reserved according to * the /etc/services database. This allows the user to reserve * mark ports as "taken" by updating that file rather than having * a ton of packages install a ton of little files that somehow * magically get accumulated to reserve ports ... * http://bugs.gentoo.org/77810 * * We do this recursively so that we dont have to worry about the * libc rebinding the same privileged port over and over again. * We keep all the sockets open until we find one we're happy * with and we keep it. */ int bind_unreserved_port(int domain, int type, int protocol) { int s; struct servent *serv; struct sockaddr_in saddr; socklen_t slen; /* allocate a socket */ s = socket(domain, type, protocol); if (s < 0) return s; /* attempt to bind to port */ if (bindresvport(s, (struct sockaddr_in *) 0) != 0) goto err_close; /* make sure we only bind to non-reserved ports */ if (getsockname(s, (struct sockaddr *)&saddr, &slen) != 0) goto err_close; serv = getservbyport(saddr.sin_port, "udp"); if (serv != NULL) { /* this port is listed in /etc/services, so let's try again */ int punt_socket = s; s = bind_unreserved_port(domain, type, protocol); close(punt_socket); } /* awesome, got ourselves a decent port */ return s; err_close: close(s); return -1; }