Programmation Avancée en C


getaddrinfo.c

00001 #include <sys/types.h>
00002 #include <sys/socket.h>
00003 #include <netinet/in.h>
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <stdlib.h>
00007 #define _POSIX_C_SOURCE 2 /* Nécessaire sur certains Linux. */
00008 #include <netdb.h>
00009 #include <arpa/inet.h>
00010 
00011 void print_flags(int f);    // Affichage du champ ai_flags.
00012 void print_family(int af);  // Affichage du champ ai_family.
00013 void print_socktype(int s); // Affichage du champ ai_socktype.
00014 void print_protocol(int p); // Affichage du champ ai_protocol.
00015 
00016 void print_addrinfo(struct addrinfo * ai) { // Affichage des infos de la liste ai.
00017         int i = 0;
00018         char *ptr = NULL;
00019         int port = 0;                // Numéro de port.
00020         char addr[INET6_ADDRSTRLEN]; // Adresse réseau.
00021 
00022         while (ai != NULL) {  // Parcours de la liste chaînée.
00023                 printf("  [%d] ",i++);
00024                 print_family(ai->ai_family);     printf("(%d) ", ai->ai_addrlen);
00025                 print_socktype(ai->ai_socktype); printf(" "); 
00026                 print_protocol(ai->ai_protocol); printf("\n");
00027                 // Récupération du numéro de port et de l'adresse IP.
00028                 switch (ai->ai_family) {
00029                 case AF_INET:  {
00030                         struct sockaddr_in *sin =
00031                                 (struct sockaddr_in *) ai->ai_addr;
00032                         ptr = (char *) inet_ntop(AF_INET, &sin->sin_addr,
00033                                                  addr, sizeof(addr));
00034                         port = sin->sin_port;
00035                         break;     }
00036                 case AF_INET6: {
00037                         struct sockaddr_in6 *sin6 =
00038                                 (struct sockaddr_in6 *) ai->ai_addr;
00039                         ptr = (char *) inet_ntop(AF_INET6, &sin6->sin6_addr,
00040                                                  addr, sizeof(addr));
00041                         port = sin6->sin6_port;
00042                         break;     }
00043                 }
00044                 if (ptr != NULL) printf("\t@IP -> %s\t port : %d\n",addr,port);
00045                 if (ai->ai_canonname != NULL)
00046                         printf("\tNom -> %s\n", ai->ai_canonname);
00047                 ai = ai->ai_next; // On passe à l'élément suivant.
00048         }
00049 }
00050 
00051 int main(int argc, char* argv[])
00052 {
00053         char *hostname = "localhost", *service = NULL;
00054         struct addrinfo indices, *res;
00055         int error;
00056 
00057         switch (argc) {
00058         case 3: service  = argv[2];
00059         case 2: hostname = argv[1];
00060         case 1: break;
00061         default: 
00062                 fprintf(stderr, "Usage: %s [hostname|@IP] [service]\n",argv[0]);
00063                 return EXIT_FAILURE;
00064         }
00065         memset(&indices, 0, sizeof(indices)); // Initialisation d'indices.
00066         indices.ai_flags = AI_CANONNAME;    // On veut une résolution de nom.
00067         indices.ai_family = AF_UNSPEC;      // Adresse IPv4 ou IPv6.
00068         indices.ai_socktype = SOCK_STREAM;  // Socket connectée.
00069         if ((error = getaddrinfo(hostname, service, &indices, &res))) {
00070                 if (error == EAI_SYSTEM) perror("  [getaddrinfo]");
00071                 fprintf(stderr, "  [getaddrinfo] %s : %s\n", hostname,
00072                         gai_strerror(error));
00073                 return EXIT_FAILURE;
00074         }
00075         print_addrinfo(res);
00076         freeaddrinfo(res); // Ne pas oublier de libérer l'espace alloué à res! /*@\label{network::getaddrinfo::freeaddrinfo}@*/
00077         return EXIT_SUCCESS;
00078 }
00079 
00080 
00081 
00082 void print_flags(int f) {
00083         switch (f) {
00084         case AI_PASSIVE:     printf("AI_PASSIVE");     break;
00085         case AI_CANONNAME:   printf("AI_CANONNAME");   break;
00086         case AI_NUMERICHOST: printf("AI_NUMERICHOST"); break;
00087         default: printf("%d Unknown",f);
00088         }
00089 }
00090 
00091 void print_family(int af) {
00092         switch (af) {
00093         case AF_INET:  printf("AF_INET");  break;
00094         case AF_INET6: printf("AF_INET6"); break;
00095         case AF_LOCAL: printf("AF_LOCAL"); break;
00096         default: printf("%d Uncommon",af);
00097         }
00098 }
00099 
00100 void print_socktype(int s) {
00101         switch (s) {
00102         case SOCK_STREAM: printf("SOCK_STREAM"); break;
00103         case SOCK_DGRAM:  printf("SOCK_DGRAM");  break;
00104         default: printf("%d Uncommon",s);
00105         }
00106 }
00107 
00108 void print_protocol(int p) {
00109         switch (p) {
00110         case IPPROTO_IP:   printf("IPPROTO_IP");   break;
00111         case IPPROTO_TCP:  printf("IPPROTO_TCP");  break;
00112         case IPPROTO_UDP:  printf("IPPROTO_UDP");  break;
00113         case IPPROTO_RAW:  printf("IPPROTO_RAW:"); break;
00114         case IPPROTO_ICMP: printf("IPPROTO_ICMP"); break;
00115         default: printf("%d Uncommon",p);
00116         }
00117 }