Varie correzioni, completata revisione capitolo sull'I/O su file
[gapil.git] / sources / mygetaddr.c
1 /* mygetaddr.c
2  * 
3  * Copyright (C) 2004 Simone Piccardi
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /*****************************************************************************
20  *
21  * File mygetaddr.c: An example for getaddrinfo program
22  *
23  * Author: S. Piccardi Nov. 2004
24  *
25  *****************************************************************************/
26 #include <string.h>      /* C strings library */
27 #include <sys/types.h>   /* primitive system data types */
28 #include <sys/stat.h>    /* file characteristics constants and functions */
29 #include <unistd.h>      /* unix standard library */
30 #include <stdlib.h>      /* C standard library */
31 #include <stdio.h>       /* standard I/O library */
32 #include <arpa/inet.h>   /* IP addresses conversion utilities */
33 #include <sys/socket.h>  /* socket constants, types and functions */
34 #include <netinet/in.h>  /* IPv4 and IPv6 constants and types */
35 #include <netdb.h>       /* C resolver library */
36
37 #include "Gapil.h"
38 /*
39  * Program mygetaddr
40  *
41  * Use getaddrinfo and print results
42  */
43 /* Help printing routine */
44 void usage(void);
45
46 int main(int argc, char *argv[]) 
47 {
48 /* 
49  * Variables definition
50  */
51     int i,j;
52     struct addrinfo hint;
53     struct addrinfo *res, *ptr;
54     int ret, port;
55     struct sockaddr_in *addr;
56     struct sockaddr_in6 *addr6;
57     char *string;
58     char buffer[INET6_ADDRSTRLEN];
59     char *protocols[] = { "tcp","udp", NULL };
60     int protval[] = { 6, 17 };
61     char *socktype[] = { "dgram","stream", NULL };
62     int sockval[] = { SOCK_DGRAM, SOCK_STREAM };
63     int debug = 0;
64     /*
65      * Init variables
66      */
67     memset(&hint, 0, sizeof(hint));
68     hint.ai_family = AF_UNSPEC;
69     /*
70      * Input section: decode command line parameters 
71      * Use getopt function
72      */
73     opterr = 0;  /* don't want writing to stderr */
74     while ( (i = getopt(argc, argv, "hdcp:t:v:")) != -1) {
75         switch (i) {
76         /* 
77          * Handling options 
78          */ 
79         case 'h':                                             /* help option */
80             printf("Wrong -h option use\n");
81             usage();
82             break;
83         case 'c':                      /* set canonical host name resolution */
84             hint.ai_flags = hint.ai_flags | AI_CANONNAME;
85             break;
86         case 'd':                      /* set canonical host name resolution */
87             debug = 1;
88             break;
89         case 'p':                                      /* set protocol value */
90             j = 0;
91             while ( (string = protocols[j]) != NULL ) {
92                 if ( (strncmp(string, optarg, strlen(string)) == 0) ) {
93                     hint.ai_protocol = protval[j];
94                     break;
95                 }
96                 j++;
97             }
98             if (j>=2) {
99                 printf("Wrong protocol, use 'tcp' or 'udp'\n\n");
100                 usage();
101             }
102             break;
103         case 't':                                   /* set socket type value */
104             j = 0;
105             while ( (string = socktype[j]) != NULL ) {
106                 if ( (strncmp(string, optarg, strlen(string)) == 0) ) {
107                     hint.ai_socktype = sockval[j];
108                     break;
109                 }
110                 j++;
111             }           
112             if (j>=2) {
113                 printf("Wrong socket type, use 'dgram' or 'stream'\n\n");
114                 usage();
115             }
116             break;
117         case 'v':                                        /* set address type */
118             j = strtol(optarg, NULL, 10);
119             if (j == 4) {
120                 hint.ai_family = AF_INET;
121                 break;
122             } 
123             if (j == 6) {
124                 hint.ai_family = AF_INET6;
125                 break;
126             }
127             printf("Wrong IP protocol version, use 4 o 6\n\n");
128             usage();
129             break;
130         case '?':                                    /* unrecognized options */
131             printf("Unrecognized options -%c\n",optopt);
132             usage();
133         default:                                       /* should not reached */
134             usage();
135         }
136     }
137     /* ***********************************************************
138      * 
139      *           Options processing completed
140      *
141      *                Main code beginning
142      * 
143      * ***********************************************************/
144     /* if debug actived printout hint values*/
145     if (debug) {
146         printf("hint.ai_flag     = %d\n", hint.ai_flags);
147         printf("hint.ai_family   = %d\n", hint.ai_family);
148         printf("hint.ai_socktype = %d\n", hint.ai_socktype);
149         printf("hint.ai_protocol = %d\n", hint.ai_protocol);
150         printf("address = %s\n", argv[optind]);
151         printf("port    = %s\n", argv[optind+1]);
152     }
153     /* remaining argument check */
154     if ((argc - optind) != 2) {
155         printf("Wrong number of arguments %d\n", argc - optind);
156         usage();
157     }
158     /* main body */    
159     ret = getaddrinfo(argv[optind], argv[optind+1], &hint, &res); 
160     if (ret != 0) {
161         printf("Resolution error %s\n", gai_strerror(ret));
162         exit(1);
163     }
164     ptr = res;                                        /* init list pointer */
165     printf("Canonical name %s\n", ptr->ai_canonname); /* print cname */
166     while (ptr != NULL) {                             /* loop on list */
167         if (ptr->ai_family == AF_INET) {              /* if IPv4 */
168             printf("IPv4 address: \n");
169             addr = (struct sockaddr_in *) ptr->ai_addr;          /* address */
170             port = ntohs(addr->sin_port);                        /* port */
171             string = inet_ntop(addr->sin_family, &addr->sin_addr, 
172                                buffer, sizeof(buffer));
173         } else if (ptr->ai_family == AF_INET6) {      /* if IPv6 */
174             printf("IPv6 address: \n");
175             addr6 = (struct sockaddr_in6 *) ptr->ai_addr;        /* address */
176             port = ntohs(addr6->sin6_port);                      /* port */
177             string = inet_ntop(addr6->sin6_family, &addr6->sin6_addr, 
178                                buffer, sizeof(buffer));
179         } else {                                      /* else is an error */
180             printf("Address family error\n");
181             exit(1);
182         }       
183         printf("\tIndirizzo %s\n", string);
184         printf("\tProtocollo %i\n", ptr->ai_protocol);
185         printf("\tPorta %i\n", port);
186         ptr = ptr->ai_next;
187     }
188     exit(0);
189 }
190 /*
191  * routine to print usage info and exit
192  */
193 void usage(void) {
194     printf("Program mygetaddr: do an hostname resolution \n");
195     printf("Usage:\n");
196     printf("mygetaddr [-h] [-p protocol] [-t socktype] hostname service\n");
197     printf("  -h              print this help\n");
198     printf("  -p udp,tcp      select a protocol\n");
199     printf("  -t dgram,stream select a socket type\n");
200     printf("  -v 4,6          select IPv4 or IPv6 \n");
201     printf("  -c              require canonical name resolution\n");
202     exit(1);
203 }