nexmon – Blame information for rev 1
?pathlinks?
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 */ |