1 /* source: xio-tun.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for opening addresses of tun/tap type */
7 #include "xiosysincludes.h"
11 #include "xio-named.h"
12 #include "xio-socket.h"
14 #include "xio-interface.h"
19 static int xioopen_tun(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xfd
, const struct addrdesc
*addrdesc
);
21 /****** TUN options ******/
22 const struct optdesc opt_tun_device
= { "tun-device", NULL
, OPT_TUN_DEVICE
, GROUP_TUN
, PH_OPEN
, TYPE_FILENAME
, OFUNC_SPEC
};
23 const struct optdesc opt_tun_name
= { "tun-name", NULL
, OPT_TUN_NAME
, GROUP_INTERFACE
, PH_FD
, TYPE_STRING
, OFUNC_SPEC
};
24 const struct optdesc opt_tun_type
= { "tun-type", NULL
, OPT_TUN_TYPE
, GROUP_INTERFACE
, PH_FD
, TYPE_STRING
, OFUNC_SPEC
};
25 const struct optdesc opt_iff_no_pi
= { "iff-no-pi", "no-pi", OPT_IFF_NO_PI
, GROUP_TUN
, PH_FD
, TYPE_BOOL
, OFUNC_SPEC
};
27 /****** TUN addresses ******/
28 const struct addrdesc xioaddr_tun
= { "TUN", 3, xioopen_tun
, GROUP_FD
|GROUP_CHR
|GROUP_OPEN
|GROUP_TUN
, 0, 0, 0 HELP("[:<ip-addr>/<bits>]") };
30 // "route"=address/netmask
31 // "ip6-route"=address/netmask
40 /* sub options for route option */
42 static const struct optdesc opt_route_tos
= { "route", NULL
, IFOPT_ROUTE
, };
43 static const struct optname xio_route_options
[] = {
44 {"tos", &xio_route_tos
}
48 static int xioopen_tun(
54 const struct addrdesc
*addrdesc
)
56 struct single
*sfd
= &xfd
->stream
;
57 char *tundevice
= NULL
;
58 char *tunname
= NULL
, *tuntype
= NULL
;
59 int pf
= /*! PF_UNSPEC*/ PF_INET
;
60 struct xiorange network
;
62 const char *namedargv
[] = { "tun", NULL
, NULL
};
63 int rw
= (xioflags
& XIO_ACCMODE
);
70 if (argc
> 2 || argc
< 0) {
72 Error3("%s: wrong number of parameters (%d instead of 0 or 1); usage: %s",
73 argv
[0], argc
-1, addrdesc
->syntax
);
75 Error2("%s: wrong number of parameters (%d instead of 0 or 1)",
80 if (retropt_string(opts
, OPT_TUN_DEVICE
, &tundevice
) != 0) {
81 tundevice
= strdup("/dev/net/tun");
84 /*! socket option here? */
85 retropt_socket_pf(opts
, &pf
);
87 namedargv
[1] = tundevice
;
88 /* open the tun cloning device */
89 if ((result
= _xioopen_named_early(2, namedargv
, xfd
, addrdesc
->groups
,
90 &exists
, opts
, addrdesc
->syntax
)) < 0) {
94 /*========================= the tunnel interface =========================*/
95 Notice("creating tunnel network interface");
96 applyopts_optgroup(&xfd
->stream
, -1, opts
, GROUP_PROCESS
);
97 if ((result
= _xioopen_open(tundevice
, rw
, opts
)) < 0)
101 /* prepare configuration of the new network interface */
102 memset(&ifr
, 0, sizeof(ifr
));
104 if (retropt_string(opts
, OPT_TUN_NAME
, &tunname
) == 0) {
105 strncpy(ifr
.ifr_name
, tunname
, IFNAMSIZ
); /* ok */
108 ifr
.ifr_name
[0] = '\0';
111 ifr
.ifr_flags
= IFF_TUN
;
112 if (retropt_string(opts
, OPT_TUN_TYPE
, &tuntype
) == 0) {
113 if (!strcmp(tuntype
, "tap")) {
114 ifr
.ifr_flags
= IFF_TAP
;
115 } else if (strcmp(tuntype
, "tun")) {
116 Error1("unknown tun-type \"%s\"", tuntype
);
120 if (retropt_bool(opts
, OPT_IFF_NO_PI
, &no_pi
) == 0) {
122 ifr
.ifr_flags
|= IFF_NO_PI
;
123 #if 0 /* not neccessary for now */
125 ifr
.ifr_flags
&= ~IFF_NO_PI
;
130 if (Ioctl(sfd
->fd
, TUNSETIFF
, &ifr
) < 0) {
131 Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s",
132 sfd
->fd
, ifr
.ifr_name
, strerror(errno
));
135 Notice1("TUN: new device \"%s\"", ifr
.ifr_name
);
137 /*===================== setting interface properties =====================*/
139 /* we seem to need a socket for manipulating the interface */
140 if ((sockfd
= Socket(PF_INET
, SOCK_DGRAM
, 0)) < 0) {
141 Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno
));
142 sockfd
= sfd
->fd
; /* desparate fallback attempt */
145 /*--------------------- setting interface address and netmask ------------*/
147 if ((ifaddr
= strdup(argv
[1])) == NULL
) {
148 Error1("strdup(\"%s\"): out of memory", argv
[1]);
149 return STAT_RETRYLATER
;
151 if ((result
= xioparsenetwork(ifaddr
, pf
, &network
,
152 sfd
->para
.socket
.ip
.ai_flags
))
157 socket_init(pf
, (union sockaddr_union
*)&ifr
.ifr_addr
);
158 ((struct sockaddr_in
*)&ifr
.ifr_addr
)->sin_addr
=
159 network
.netaddr
.ip4
.sin_addr
;
160 if (Ioctl(sockfd
, SIOCSIFADDR
, &ifr
) < 0) {
161 Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s",
162 sockfd
, ifr
.ifr_name
, ifaddr
, strerror(errno
));
164 ((struct sockaddr_in
*)&ifr
.ifr_netmask
)->sin_addr
=
165 network
.netmask
.ip4
.sin_addr
;
166 if (Ioctl(sockfd
, SIOCSIFNETMASK
, &ifr
) < 0) {
167 Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s",
168 sockfd
, ((struct sockaddr_in
*)&ifr
.ifr_netmask
)->sin_addr
.s_addr
,
169 ifaddr
, strerror(errno
));
173 /*--------------------- setting interface flags --------------------------*/
174 applyopts_single(sfd
, opts
, PH_FD
);
176 _xiointerface_apply_iff(sockfd
, ifr
.ifr_name
, sfd
->para
.interface
.iff_opts
);
177 if (_interface_retrieve_vlan(&xfd
->stream
, opts
) < 0)
180 applyopts(sfd
, -1, opts
, PH_FD
);
181 applyopts_cloexec(sfd
->fd
, opts
);
183 applyopts_fchown(sfd
->fd
, opts
);
185 if ((result
= _xio_openlate(sfd
, opts
)) < 0)
191 #endif /* WITH_TUN */