| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- #include "gai_hdr.h"
- /*
- * Go through all the addrinfo structures, checking for a match of the
- * socket type and filling in the socket type, and then the port number
- * in the corresponding socket address structures.
- *
- * The AI_CLONE flag works as follows. Consider a multihomed host with
- * two IP addresses and no socket type specified by the caller. After
- * the "host" search there are two addrinfo structures, one per IP address.
- * Assuming a service supported by both TCP and UDP (say the daytime
- * service) we need to return *four* addrinfo structures:
- * IP#1, SOCK_STREAM, TCP port,
- * IP#1, SOCK_DGRAM, UDP port,
- * IP#2, SOCK_STREAM, TCP port,
- * IP#2, SOCK_DGRAM, UDP port.
- * To do this, when the "host" loop creates an addrinfo structure, if the
- * caller has not specified a socket type (hintsp->ai_socktype == 0), the
- * AI_CLONE flag is set. When the following function finds an entry like
- * this it is handled as follows: If the entry's ai_socktype is still 0,
- * this is the first use of the structure, and the ai_socktype field is set.
- * But, if the entry's ai_socktype is nonzero, then we clone a new addrinfo
- * structure and set it's ai_socktype to the new value. Although we only
- * need two socket types today (SOCK_STREAM and SOCK_DGRAM) this algorithm
- * will handle any number. Also notice that Posix.1g requires all socket
- * types to be nonzero.
- */
- /* include ga_port */
- int
- ga_port(struct addrinfo *aihead, int port, int socktype)
- /* port must be in network byte order */
- {
- int nfound = 0;
- struct addrinfo *ai;
- for (ai = aihead; ai != NULL; ai = ai->ai_next) {
- if (ai->ai_flags & AI_CLONE) {
- if (ai->ai_socktype != 0) {
- if ( (ai = ga_clone(ai)) == NULL)
- return(-1); /* memory allocation error */
- /* ai points to newly cloned entry, which is what we want */
- }
- } else if (ai->ai_socktype != socktype)
- continue; /* ignore if mismatch on socket type */
- ai->ai_socktype = socktype;
- switch (ai->ai_family) {
- #ifdef IPv4
- case AF_INET:
- ((struct sockaddr_in *) ai->ai_addr)->sin_port = port;
- nfound++;
- break;
- #endif
- #ifdef IPv6
- case AF_INET6:
- ((struct sockaddr_in6 *) ai->ai_addr)->sin6_port = port;
- nfound++;
- break;
- #endif
- }
- }
- return(nfound);
- }
- /* end ga_port */
|