Imported Upstream version 0.1.17
[platform/upstream/libnice.git] / stun / tools / stunbdc.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2008-2009 Collabora Ltd.
5  *  Contact: Youness Alaoui
6  * (C) 2007-2009 Nokia Corporation. All rights reserved.
7  *  Contact: Rémi Denis-Courmont
8  *
9  * The contents of this file are subject to the Mozilla Public License Version
10  * 1.1 (the "License"); you may not use this file except in compliance with
11  * the License. You may obtain a copy of the License at
12  * http://www.mozilla.org/MPL/
13  *
14  * Software distributed under the License is distributed on an "AS IS" basis,
15  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16  * for the specific language governing rights and limitations under the
17  * License.
18  *
19  * The Original Code is the Nice GLib ICE library.
20  *
21  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22  * Corporation. All Rights Reserved.
23  *
24  * Contributors:
25  *   Youness Alaoui, Collabora Ltd.
26  *   Rémi Denis-Courmont, Nokia
27  *
28  * Alternatively, the contents of this file may be used under the terms of the
29  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
30  * case the provisions of LGPL are applicable instead of those above. If you
31  * wish to allow use of your version of this file only under the terms of the
32  * LGPL and not to allow others to use your version of this file under the
33  * MPL, indicate your decision by deleting the provisions above and replace
34  * them with the notice and other provisions required by the LGPL. If you do
35  * not delete the provisions above, a recipient may use your version of this
36  * file under either the MPL or the LGPL.
37  */
38
39 #ifdef HAVE_CONFIG_H
40 # include <config.h>
41 #endif
42
43 #ifdef _WIN32
44 #  include <winsock2.h>
45 #else
46 #  include <sys/socket.h>
47 #  include <netdb.h>
48 #endif
49
50 #include <sys/types.h>
51 #include "stun/stunagent.h"
52 #include "stun/usages/bind.h"
53
54 #ifdef HAVE_UNISTD_H
55 #include <unistd.h>
56 #endif
57
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <string.h>
61
62 static int ai_flags = 0;
63
64 static void
65 printaddr (const char *str, const struct sockaddr *addr, socklen_t addrlen)
66 {
67   char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
68
69   int val = getnameinfo (addr, addrlen, hostbuf, sizeof (hostbuf),
70                          servbuf, sizeof (servbuf),
71                          NI_NUMERICHOST | NI_NUMERICSERV);
72   if (val)
73     printf ("%s: %s\n", str, gai_strerror (val));
74   else
75     printf ("%s: %s port %s\n", str, hostbuf, servbuf);
76 }
77
78
79
80 static int run (int family, const char *hostname, const char *service)
81 {
82   struct addrinfo hints, *res;
83   const struct addrinfo *ptr;
84   int ret = -1;
85
86   memset (&hints, 0, sizeof (hints));
87   hints.ai_family = family;
88   hints.ai_socktype = SOCK_DGRAM;
89   hints.ai_flags = ai_flags;
90   if (service == NULL)
91     service = "3478";
92
93   ret = getaddrinfo (hostname, service, &hints, &res);
94   if (ret)
95   {
96     fprintf (stderr, "%s (port %s): %s\n", hostname, service,
97              gai_strerror (ret));
98     return -1;
99   }
100
101   for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
102   {
103     union {
104       struct sockaddr_storage storage;
105       struct sockaddr addr;
106     } addr;
107     socklen_t addrlen = sizeof (addr);
108     StunUsageBindReturn val;
109
110     printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen);
111
112     val = stun_usage_bind_run (ptr->ai_addr, ptr->ai_addrlen, &addr.storage,
113         &addrlen);
114     if (val)
115       fprintf (stderr, "%d\n", val);
116     else
117     {
118       printaddr ("Mapped address", &addr.addr, addrlen);
119       ret = 0;
120     }
121   }
122
123   freeaddrinfo (res);
124   return ret;
125 }
126
127
128 int main (int argc, char *argv[])
129 {
130   const char *server = NULL, *port = NULL;
131   int family = AF_UNSPEC;
132   int i;
133   int result;
134
135 #ifdef _WIN32
136   WSADATA w;
137   WSAStartup (0x0202, &w);
138 #endif
139
140   for (i = 1; i < argc; ++i)
141   {
142     const char *arg = argv[i];
143
144     if (arg[0] != '-')
145       break;
146
147     if (strcmp (arg, "--ipv4") == 0 || strcmp (arg, "-4") == 0)
148     {
149       family = AF_INET;
150     }
151     else if (strcmp (arg, "--ipv6") == 0 || strcmp (arg, "-6") == 0)
152     {
153       family = AF_INET6;
154     }
155     else if (strcmp (arg, "--help") == 0 || strcmp (arg, "-h") == 0)
156     {
157       printf ("Usage: %s [-4|-6] <server> [port number]\n"
158               "Performs STUN Binding Discovery\n"
159               "\n"
160               "  -4, --ipv4    Force IP version 4\n"
161               "  -6, --ipv6    Force IP version 6\n"
162               "  -n, --numeric Server in numeric form\n"
163               "\n", argv[0]);
164       return 0;
165     }
166     else if (strcmp (arg, "--numeric") == 0 || strcmp (arg, "-n") == 0)
167     {
168       ai_flags |= AI_NUMERICHOST;
169     }
170     else if (strcmp (arg, "--version") == 0 || strcmp (arg, "-V") == 0)
171     {
172       printf ("stunbcd: STUN Binding Discovery client (%s v%s)\n",
173               PACKAGE, VERSION);
174       return 0;
175     } else {
176       fprintf (stderr, "Unexpected command line argument '%s'", arg);
177       return 2;
178     }
179   }
180
181   if (i < argc)
182     server = argv[i++];
183   if (i < argc)
184     port = argv[i++];
185   if (i < argc)
186   {
187     fprintf (stderr, "%s: extra parameter `%s'\n", argv[0], argv[i]);
188     return 2;
189   }
190
191   result = run (family, server, port) ? 1 : 0;
192
193 #ifdef _WIN32
194   WSACleanup();
195 #endif
196
197   return result;
198 }