nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* source: xio-tun.c */
2 /* Copyright Gerhard Rieger */
3 /* Published under the GNU General Public License V.2, see file COPYING */
4  
5 /* this file contains the source for opening addresses of tun/tap type */
6  
7 #include "xiosysincludes.h"
8 #if WITH_TUN
9 #include "xioopen.h"
10  
11 #include "xio-named.h"
12 #include "xio-socket.h"
13 #include "xio-ip.h"
14  
15 #include "xio-tun.h"
16  
17  
18 static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
19  
20 /****** TUN addresses ******/
21 const struct optdesc opt_tun_device = { "tun-device", NULL, OPT_TUN_DEVICE, GROUP_TUN, PH_OPEN, TYPE_FILENAME, OFUNC_SPEC };
22 const struct optdesc opt_tun_name = { "tun-name", NULL, OPT_TUN_NAME, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };
23 const struct optdesc opt_tun_type = { "tun-type", NULL, OPT_TUN_TYPE, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };
24 const struct optdesc opt_iff_no_pi = { "iff-no-pi", "no-pi", OPT_IFF_NO_PI, GROUP_TUN, PH_FD, TYPE_BOOL, OFUNC_SPEC };
25 /*0 const struct optdesc opt_interface_addr = { "interface-addr", "address", OPT_INTERFACE_ADDR, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/
26 /*0 const struct optdesc opt_interface_netmask = { "interface-netmask", "netmask", OPT_INTERFACE_NETMASK, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/
27 const struct optdesc opt_iff_up = { "iff-up", "up", OPT_IFF_UP, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_UP };
28 const struct optdesc opt_iff_broadcast = { "iff-broadcast", NULL, OPT_IFF_BROADCAST, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_BROADCAST };
29 const struct optdesc opt_iff_debug = { "iff-debug" , NULL, OPT_IFF_DEBUG, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_DEBUG };
30 const struct optdesc opt_iff_loopback = { "iff-loopback" , "loopback", OPT_IFF_LOOPBACK, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_LOOPBACK };
31 const struct optdesc opt_iff_pointopoint = { "iff-pointopoint", "pointopoint",OPT_IFF_POINTOPOINT, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_POINTOPOINT };
32 const struct optdesc opt_iff_notrailers = { "iff-notrailers", "notrailers", OPT_IFF_NOTRAILERS, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_NOTRAILERS };
33 const struct optdesc opt_iff_running = { "iff-running", "running", OPT_IFF_RUNNING, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_RUNNING };
34 const struct optdesc opt_iff_noarp = { "iff-noarp", "noarp", OPT_IFF_NOARP, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_NOARP };
35 const struct optdesc opt_iff_promisc = { "iff-promisc", "promisc", OPT_IFF_PROMISC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_PROMISC };
36 const struct optdesc opt_iff_allmulti = { "iff-allmulti", "allmulti", OPT_IFF_ALLMULTI, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_ALLMULTI };
37 const struct optdesc opt_iff_master = { "iff-master", "master", OPT_IFF_MASTER, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_MASTER };
38 const struct optdesc opt_iff_slave = { "iff-slave", "slave", OPT_IFF_SLAVE, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_SLAVE };
39 const struct optdesc opt_iff_multicast = { "iff-multicast", NULL, OPT_IFF_MULTICAST, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_MULTICAST };
40 const struct optdesc opt_iff_portsel = { "iff-portsel", "portsel", OPT_IFF_PORTSEL, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_PORTSEL };
41 const struct optdesc opt_iff_automedia = { "iff-automedia", "automedia", OPT_IFF_AUTOMEDIA, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_AUTOMEDIA };
42 /*const struct optdesc opt_iff_dynamic = { "iff-dynamic", "dynamic", OPT_IFF_DYNAMIC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.tun.iff_opts), XIO_SIZEOF(para.tun.iff_opts), IFF_DYNAMIC };*/
43 #if LATER
44 const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
45 #endif
46  
47 static const struct xioaddr_endpoint_desc xioendpoint_tun1 = { XIOADDR_SYS, "tun", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_TUN, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_tun, 0, 0, 0 HELP(":<ip-addr>/<bits>") };
48  
49 const union xioaddr_desc *xioaddrs_tun[] = {
50 (union xioaddr_desc *)&xioendpoint_tun1,
51 NULL
52 };
53 /* "if-name"=tun3
54 // "route"=address/netmask
55 // "ip6-route"=address/netmask
56 // "iff-broadcast"
57 // "iff-debug"
58 // "iff-promisc"
59 // see .../linux/if.h
60 */
61  
62  
63 #if LATER
64 /* sub options for route option */
65 #define IFOPT_ROUTE 1
66 static const struct optdesc opt_route_tos = { "route", NULL, IFOPT_ROUTE, };
67 static const struct optname xio_route_options[] = {
68 {"tos", &xio_route_tos }
69 } ;
70 #endif
71  
72 static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3) {
73 char *tundevice = NULL;
74 char *tunname = NULL, *tuntype = NULL;
75 int pf = /*! PF_UNSPEC*/ PF_INET;
76 struct xiorange network;
77 bool no_pi = false;
78 const char *namedargv[] = { "tun", NULL, NULL };
79 int rw = (xioflags & XIO_ACCMODE);
80 bool exists;
81 struct ifreq ifr;
82 int sockfd;
83 char *ifaddr;
84 int result;
85  
86 if (argc > 2 || argc < 0) {
87 Error2("%s: wrong number of parameters (%d instead of 0 or 1)",
88 argv[0], argc-1);
89 }
90  
91 if (retropt_string(opts, OPT_TUN_DEVICE, &tundevice) != 0) {
92 tundevice = strdup("/dev/net/tun");
93 }
94  
95 /*! socket option here? */
96 retropt_socket_pf(opts, &pf);
97  
98 namedargv[1] = tundevice;
99 /* open the tun cloning device */
100 if ((result = _xioopen_named_early(2, namedargv, xfd, groups, &exists, opts)) < 0) {
101 return result;
102 }
103  
104 /*========================= the tunnel interface =========================*/
105 Notice("creating tunnel network interface");
106 if ((result = _xioopen_open(tundevice, rw, opts)) < 0)
107 return result;
108 if (XIOWITHRD(rw)) xfd->stream.rfd = result;
109 if (XIOWITHWR(rw)) xfd->stream.wfd = result;
110  
111 /* prepare configuration of the new network interface */
112 memset(&ifr, 0,sizeof(ifr));
113  
114 if (retropt_string(opts, OPT_TUN_NAME, &tunname) == 0) {
115 strncpy(ifr.ifr_name, tunname, IFNAMSIZ); /* ok */
116 free(tunname);
117 } else {
118 ifr.ifr_name[0] = '\0';
119 }
120  
121 ifr.ifr_flags = IFF_TUN;
122 if (retropt_string(opts, OPT_TUN_TYPE, &tuntype) == 0) {
123 if (!strcmp(tuntype, "tap")) {
124 ifr.ifr_flags = IFF_TAP;
125 } else if (strcmp(tuntype, "tun")) {
126 Error1("unknown tun-type \"%s\"", tuntype);
127 }
128 }
129  
130 if (retropt_bool(opts, OPT_IFF_NO_PI, &no_pi) == 0) {
131 if (no_pi) {
132 ifr.ifr_flags |= IFF_NO_PI;
133 #if 0 /* not neccessary for now */
134 } else {
135 ifr.ifr_flags &= ~IFF_NO_PI;
136 #endif
137 }
138 }
139  
140 if (Ioctl(xfd->stream.rfd, TUNSETIFF, &ifr) < 0) {
141 Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s",
142 xfd->stream.rfd, ifr.ifr_name, strerror(errno));
143 Close(xfd->stream.rfd);
144 }
145  
146 /*===================== setting interface properties =====================*/
147  
148 /* we seem to need a socket for manipulating the interface */
149 if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
150 Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno));
151 sockfd = xfd->stream.rfd; /* desparate fallback attempt */
152 }
153  
154 /*--------------------- setting interface address and netmask ------------*/
155 if (argc == 2) {
156 if ((ifaddr = strdup(argv[1])) == NULL) {
157 Error1("strdup(\"%s\"): out of memory", argv[1]);
158 return STAT_RETRYLATER;
159 }
160 if ((result = xioparsenetwork(ifaddr, pf, &network)) != STAT_OK) {
161 /*! recover */
162 return result;
163 }
164 socket_init(pf, (union sockaddr_union *)&ifr.ifr_addr);
165 ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr =
166 network.netaddr.ip4.sin_addr;
167 if (Ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
168 Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s",
169 sockfd, ifr.ifr_name, ifaddr, strerror(errno));
170 }
171 ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr =
172 network.netmask.ip4.sin_addr;
173 if (Ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
174 Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s",
175 sockfd, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr,
176 ifaddr, strerror(errno));
177 }
178 free(ifaddr);
179 }
180 /*--------------------- setting interface flags --------------------------*/
181 applyopts_single(&xfd->stream, opts, PH_FD);
182  
183 if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
184 Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s",
185 sockfd, ifr.ifr_name, strerror(errno));
186 }
187 Debug2("\"%s\": system set flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
188 ifr.ifr_flags |= xfd->stream.para.tun.iff_opts[0];
189 ifr.ifr_flags &= ~xfd->stream.para.tun.iff_opts[1];
190 Debug2("\"%s\": xio merged flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
191 if (Ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
192 Error4("ioctl(%d, SIOCSIFFLAGS, {\"%s\", %hd}: %s",
193 sockfd, ifr.ifr_name, ifr.ifr_flags, strerror(errno));
194 }
195 ifr.ifr_flags = 0;
196 if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
197 Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s",
198 sockfd, ifr.ifr_name, strerror(errno));
199 }
200 Debug2("\"%s\": resulting flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
201  
202  
203 #if LATER
204 applyopts_named(tundevice, opts, PH_FD);
205 #endif
206 applyopts(xfd->stream.rfd, opts, PH_FD);
207 applyopts_cloexec(xfd->stream.rfd, opts);
208  
209 applyopts_fchown(xfd->stream.rfd, opts);
210  
211 if ((result = _xio_openlate(&xfd->stream, opts)) < 0)
212 return result;
213  
214 return 0;
215 }
216  
217 #endif /* WITH_TUN */