1 : /*
2 : * diag.c - IPv6 tunnel diagnostic functions
3 : * $Id: diag.c 1726 2006-08-27 08:13:18Z remi $
4 : */
5 :
6 : /***********************************************************************
7 : * Copyright © 2004-2006 Rémi Denis-Courmont. *
8 : * This program is free software; you can redistribute and/or modify *
9 : * it under the terms of the GNU General Public License as published *
10 : * by the Free Software Foundation; version 2 of the license. *
11 : * *
12 : * This program is distributed in the hope that it will be useful, *
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
15 : * See the GNU General Public License for more details. *
16 : * *
17 : * You should have received a copy of the GNU General Public License *
18 : * along with this program; if not, you can get it from: *
19 : * http://www.gnu.org/copyleft/gpl.html *
20 : ***********************************************************************/
21 :
22 : #ifdef HAVE_CONFIG_H
23 : # include <config.h>
24 : #endif
25 :
26 : #include <gettext.h>
27 :
28 : #include <assert.h>
29 :
30 : #include <stdio.h>
31 : #include <string.h>
32 :
33 : #include <sys/types.h>
34 : #include <sys/stat.h>
35 : #include <fcntl.h>
36 : #include <unistd.h>
37 : #include <errno.h>
38 :
39 : #include <sys/socket.h> // socket(AF_INET6, SOCK_DGRAM, 0)
40 : #include <libtun6/tun6.h>
41 :
42 : extern const char os_driver[];
43 :
44 : /**
45 : * Checks if libtun6 should be able to tun on system.
46 : *
47 : * @param errbuf a buffer of at least LIBTUN6_ERRBUF_SIZE bytes
48 : * to hold an error message suitable for the user attention.
49 : * Also set on success.
50 : *
51 : * @return 0 on success, -1 if the system seems inadequate.
52 : */
53 : int tun6_driver_diagnose (char *errbuf)
54 3 : {
55 : (void)bindtextdomain (PACKAGE_NAME, LOCALEDIR);
56 :
57 3 : int fd = socket (AF_INET6, SOCK_DGRAM, 0);
58 3 : if (fd == -1)
59 : {
60 0 : strlcpy (errbuf, "Error: IPv6 stack not available.\n",
61 : LIBTUN6_ERRBUF_SIZE - 1);
62 0 : errbuf[LIBTUN6_ERRBUF_SIZE - 1] = '\0';
63 0 : return -1;
64 : }
65 3 : (void)close (fd);
66 :
67 : #if defined (__linux__)
68 3 : const char tundev[] = "/dev/net/tun";
69 : #else
70 : const char tundev[] = "/dev/tun0";
71 : #endif
72 :
73 3 : fd = open (tundev, O_RDWR);
74 3 : if (fd >= 0)
75 : {
76 3 : (void)close (fd);
77 3 : snprintf (errbuf, LIBTUN6_ERRBUF_SIZE - 1,
78 : "%s tunneling driver found.", os_driver);
79 3 : errbuf[LIBTUN6_ERRBUF_SIZE - 1] = '\0';
80 3 : return 0;
81 : }
82 :
83 0 : if (errno == ENOENT)
84 : {
85 : const char *specific;
86 :
87 : #if defined (__linux__)
88 0 : specific = N_("You should run these commands to create it:\n"
89 : "# mkdir -p /dev/net\n"
90 : "# mknod /dev/net/tun c 10 200\n"
91 : "(you must be root to do that).\n");
92 : #elif defined (__APPLE__)
93 : specific = N_("You can obtain a tunnel driver for the "
94 : "Darwin kernel (Mac OS X) from:\n"
95 : "http://www-user.rhrk.uni-kl.de/~nissler/tuntap/\n");
96 : #else
97 : specific = NULL;
98 : #endif
99 :
100 0 : snprintf (errbuf, LIBTUN6_ERRBUF_SIZE - 1,
101 : _("Error: %s character device "
102 : "not found or unavailable.\n%s"), tundev,
103 : specific != NULL ? dgettext (PACKAGE_NAME, specific) : "");
104 0 : errbuf[LIBTUN6_ERRBUF_SIZE - 1] = '\0';
105 0 : return -1;
106 : }
107 : else
108 : /* Linux returns ENODEV instead of ENXIO */
109 0 : if ((errno == ENXIO) || (errno == ENODEV))
110 : {
111 : const char *specific;
112 :
113 : #if defined (__linux__)
114 0 : specific = N_("Make sure your Linux kernel includes "
115 : "the \"Universal TUNTAP driver\"\n"
116 : "(CONFIG_TUN option), possibly as a module.\n");
117 : #elif defined (__APPLE__)
118 : specific = N_("You can obtain a tunnel driver for the "
119 : "Darwin kernel (Mac OS X) from:\n"
120 : "http://www-user.rhrk.uni-kl.de/~nissler/tuntap/\n");
121 : #else
122 : specific = NULL;
123 : #endif
124 :
125 0 : snprintf (errbuf, LIBTUN6_ERRBUF_SIZE - 1,
126 : _("Error: your operating system does not "
127 : "seem to provide a network tunneling\n"
128 : "device driver, which is required.\n%s"),
129 : specific != NULL ? gettext (specific) : "");
130 0 : errbuf[LIBTUN6_ERRBUF_SIZE - 1] = '\0';
131 0 : return -1;
132 : }
133 :
134 0 : snprintf (errbuf, LIBTUN6_ERRBUF_SIZE - 1,
135 : _("Error: cannot open device file %s (%s)\n"
136 : "IPv6 tunneling will not work.\n"), tundev,
137 : strerror (errno));
138 0 : errbuf[LIBTUN6_ERRBUF_SIZE - 1] = '\0';
139 0 : return -1;
140 : }
141 :
|