/* getaddrinfo.c : PUBLIC DOMAIN - Jon Mayo - August 14, 2006 * - You may remove any comments you wish, modify this code any way you wish, * and distribute any way you wish. */ /* generic networking routines */ #include #include #include #include #include struct net_handler { void (*connect_handler)(void *p, int fd, const char *addr, const char *serv); void *connect_p; void (*io_handler)(int fd, short ev, void *p); void *io_p; }; static int net_lookup(const char *host, const char *sport, const char *pname, int (*foreach)(void *p, struct addrinfo *ai, const char *addr, const char *serv), void *p) { struct protoent *pe; struct addrinfo *ai, hint, *curr; int proto; int res; assert(foreach != NULL); fprintf(stderr, "net_lookup(%s, %s, %s)\n", host, sport, pname); if(pname) { pe=getprotobyname(pname); proto=pe ? pe->p_proto : 0; } else { proto=0; } if(host && !host[0]) host=0; if(sport && !sport[0]) sport=0; hint.ai_flags=AI_ADDRCONFIG|AI_PASSIVE; hint.ai_family=PF_UNSPEC; hint.ai_socktype=0; /* set to SOCK_STREAM if you do not want UDP */ hint.ai_protocol=proto; hint.ai_addrlen=0; hint.ai_addr=0; hint.ai_canonname=0; hint.ai_next=0; if((res=getaddrinfo(host, sport, &hint, &ai))) { fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(res)); if(res==EAI_SYSTEM) { perror("getaddrinfo()"); } return 0; } curr=ai; if(!curr) { fprintf(stderr, "no entries!\n"); return 0; } for(; curr; curr=curr->ai_next) { char addr[NI_MAXHOST]; char serv[NI_MAXSERV]; int res; if((res=getnameinfo(curr->ai_addr, curr->ai_addrlen, addr, sizeof addr, serv, sizeof serv, NI_NUMERICHOST))) { /* Failed */ if(res==EAI_SYSTEM) { perror("getnameinfo()"); } else { fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(res)); } continue; } if(!foreach(p, curr, addr, serv)) { freeaddrinfo(ai); return 0; } } freeaddrinfo(ai); return 1; } #ifdef STAND_ALONE int dump_entry(void *p, struct addrinfo *ai, const char *addr, const char *serv) { int s; assert(ai != NULL); fprintf(stderr, "family: %u\tsocktype: %u\tprotocol: %u\taddr: %s/%s\n", ai->ai_family, ai->ai_socktype, ai->ai_protocol, addr, serv); /* example of using the addrinfo structure to create a socket to use * with bind() or connect(). */ s=socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s < 0) { perror("socket()"); return 0; } /* TODO: now do something with s */ return 1; } /* usage: * getaddrinfo [ [tcp|udp]] */ int main(int argc, char **argv) { const char *sport, *host, *proto; host = (argc>1) ? argv[1] : ""; sport = (argc>2) ? argv[2] : "23"; proto = (argc>3) ? argv[3] : "tcp"; fprintf(stderr, "Host '%s' on port '%s' using '%s'\n", host, sport, proto); net_lookup(host, sport, proto, dump_entry, 0); return 0; } #endif