File: | src/usr.sbin/npppd/npppd/npppd_iface.c |
Warning: | line 233, column 15 Value stored to 'sock' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: npppd_iface.c,v 1.15 2021/02/01 07:44:58 mvs Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2009 Internet Initiative Japan Inc. |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. |
27 | */ |
28 | /* $Id: npppd_iface.c,v 1.15 2021/02/01 07:44:58 mvs Exp $ */ |
29 | /**@file |
30 | * The interface of npppd and kernel. |
31 | * This is an implementation to use tun(4) or pppx(4). |
32 | */ |
33 | #include <sys/types.h> |
34 | #include <sys/ioctl.h> |
35 | #include <sys/socket.h> |
36 | #include <sys/uio.h> |
37 | #include <sys/sockio.h> |
38 | #include <netinet/in.h> |
39 | #include <netinet/ip.h> |
40 | #include <arpa/inet.h> |
41 | #include <net/if_dl.h> |
42 | #include <net/if_tun.h> |
43 | #include <net/if_types.h> |
44 | #include <net/if.h> |
45 | #include <net/pipex.h> |
46 | |
47 | #include <fcntl.h> |
48 | |
49 | #include <syslog.h> |
50 | #include <stdio.h> |
51 | #include <stdlib.h> |
52 | #include <string.h> |
53 | #include <unistd.h> |
54 | #include <errno(*__errno()).h> |
55 | #include <stdarg.h> |
56 | |
57 | #include <time.h> |
58 | #include <event.h> |
59 | #include "radish.h" |
60 | |
61 | #include "npppd_defs.h" |
62 | #include "npppd_local.h" |
63 | #include "npppd_subr.h" |
64 | #include "debugutil.h" |
65 | #include "npppd_iface.h" |
66 | |
67 | #ifdef USE_NPPPD_PIPEX1 |
68 | #include <net/if.h> |
69 | #if defined(__NetBSD__) |
70 | #include <net/if_ether.h> |
71 | #else |
72 | #include <netinet/if_ether.h> |
73 | #endif |
74 | #include <net/pipex.h> |
75 | #endif /* USE_NPPPD_PIPEX */ |
76 | |
77 | #ifdef NPPPD_IFACE_DEBUG |
78 | #define NPPPD_IFACE_DBG(x) npppd_iface_log x |
79 | #define NPPPD_IFACE_ASSERT(cond) \ |
80 | if (!(cond)) { \ |
81 | fprintf(stderr(&__sF[2]), \ |
82 | "\nASSERT(" #cond ") failed on %s() at %s:%d.\n"\ |
83 | , __func__, __FILE__"/usr/src/usr.sbin/npppd/npppd/npppd_iface.c", __LINE__83); \ |
84 | abort(); \ |
85 | } |
86 | #else |
87 | #define NPPPD_IFACE_ASSERT(cond) |
88 | #define NPPPD_IFACE_DBG(x) |
89 | #endif |
90 | |
91 | static void npppd_iface_network_input_ipv4(npppd_iface *, struct pppx_hdr *, |
92 | u_char *, int); |
93 | static void npppd_iface_network_input(npppd_iface *, u_char *, int); |
94 | static int npppd_iface_setup_ip(npppd_iface *); |
95 | static void npppd_iface_io_event_handler (int, short, void *); |
96 | static int npppd_iface_log (npppd_iface *, int, const char *, ...) |
97 | __printflike(3,4)__attribute__((__format__ (__printf__, 3, 4))); |
98 | |
99 | |
100 | /** initialize npppd_iface */ |
101 | void |
102 | npppd_iface_init(npppd *npppd, npppd_iface *_this, struct iface *iface) |
103 | { |
104 | |
105 | NPPPD_IFACE_ASSERT(_this != NULL); |
106 | memset(_this, 0, sizeof(npppd_iface)); |
107 | |
108 | _this->npppd = npppd; |
109 | strlcpy(_this->ifname, iface->name, sizeof(_this->ifname)); |
110 | _this->using_pppx = iface->is_pppx; |
111 | _this->set_ip4addr = 1; |
112 | _this->ip4addr = iface->ip4addr; |
113 | _this->ipcpconf = iface->ipcpconf; |
114 | _this->devf = -1; |
115 | _this->initialized = 1; |
116 | } |
117 | |
118 | static int |
119 | npppd_iface_setup_ip(npppd_iface *_this) |
120 | { |
121 | int sock, if_flags, changed; |
122 | struct in_addr gw, assigned; |
123 | struct sockaddr_in *sin0; |
124 | struct ifreq ifr; |
125 | struct ifaliasreq ifra; |
126 | npppd_ppp *ppp; |
127 | |
128 | NPPPD_IFACE_ASSERT(_this != NULL); |
129 | |
130 | sock = -1; |
131 | changed = 0; |
132 | memset(&ifr, 0, sizeof(ifr)); |
133 | |
134 | /* get address which was assigned to interface */ |
135 | assigned.s_addr = INADDR_NONE((u_int32_t)(0xffffffff)); |
136 | memset(&ifr, 0, sizeof(ifr)); |
137 | memset(&ifra, 0, sizeof(ifra)); |
138 | strlcpy(ifr.ifr_name, _this->ifname, sizeof(ifr.ifr_name)); |
139 | strlcpy(ifra.ifra_name, _this->ifname, sizeof(ifra.ifra_name)); |
140 | sin0 = (struct sockaddr_in *)&ifr.ifr_addrifr_ifru.ifru_addr; |
141 | |
142 | if (priv_get_if_addr(_this->ifname, &assigned) != 0) { |
143 | if (errno(*__errno()) != EADDRNOTAVAIL49) { |
144 | npppd_iface_log(_this, LOG_ERR3, |
145 | "get ip address failed: %m"); |
146 | goto fail; |
147 | } |
148 | assigned.s_addr = 0; |
149 | } |
150 | |
151 | if (assigned.s_addr != _this->ip4addr.s_addr) |
152 | changed = 1; |
153 | |
154 | if (priv_get_if_flags(_this->ifname, &if_flags) != 0) { |
155 | npppd_iface_log(_this, LOG_ERR3, |
156 | "ioctl(,SIOCGIFFLAGS) failed: %m"); |
157 | goto fail; |
158 | } |
159 | if_flags = ifr.ifr_flagsifr_ifru.ifru_flags; |
160 | if (_this->set_ip4addr != 0 && changed) { |
161 | do { |
162 | struct in_addr dummy; |
163 | if (priv_delete_if_addr(_this->ifname) != 0) { |
164 | if (errno(*__errno()) == EADDRNOTAVAIL49) |
165 | break; |
166 | npppd_iface_log(_this, LOG_ERR3, |
167 | "delete ipaddress %s failed: %m", |
168 | _this->ifname); |
169 | goto fail; |
170 | } |
171 | if (priv_get_if_addr(_this->ifname, &dummy) != 0) { |
172 | if (errno(*__errno()) == EADDRNOTAVAIL49) |
173 | break; |
174 | npppd_iface_log(_this, LOG_ERR3, |
175 | "cannot get ipaddress %s failed: %m", |
176 | _this->ifname); |
177 | goto fail; |
178 | } |
179 | } while (1); |
180 | |
181 | /* ifconfig tun1 down */ |
182 | if (priv_set_if_flags(_this->ifname, |
183 | if_flags & ~(IFF_UP0x1 | IFF_BROADCAST0x2)) != 0) { |
184 | npppd_iface_log(_this, LOG_ERR3, |
185 | "disabling %s failed: %m", _this->ifname); |
186 | goto fail; |
187 | } |
188 | if (priv_set_if_addr(_this->ifname, &_this->ip4addr) != 0 && |
189 | errno(*__errno()) != EEXIST17) { |
190 | npppd_iface_log(_this, LOG_ERR3, |
191 | "Cannot assign tun device ip address: %m"); |
192 | goto fail; |
193 | } |
194 | /* erase old route */ |
195 | if (assigned.s_addr != 0) { |
196 | gw.s_addr = htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ? (__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff ) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001)) ) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001 ))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)( 0x7f000001)))); |
197 | in_host_route_delete(&assigned, &gw); |
198 | } |
199 | |
200 | assigned.s_addr = _this->ip4addr.s_addr; |
201 | |
202 | } |
203 | _this->ip4addr.s_addr = assigned.s_addr; |
204 | if (npppd_iface_ip_is_ready(_this)((_this)->initialized != 0 && (_this)->ip4addr. s_addr != ((u_int32_t)(0x00000000)))) { |
205 | if (changed) { |
206 | /* |
207 | * If there is a PPP session which was assigned |
208 | * interface IP address, disconnect it. |
209 | */ |
210 | ppp = npppd_get_ppp_by_ip(_this->npppd, _this->ip4addr); |
211 | if (ppp != NULL((void *)0)) { |
212 | npppd_iface_log(_this, LOG_ERR3, |
213 | "Assigning %s, but ppp=%d is using " |
214 | "the address. Requested the ppp to stop", |
215 | inet_ntoa(_this->ip4addr), ppp->id); |
216 | ppp_stop(ppp, "Administrative reason"); |
217 | } |
218 | } |
219 | /* ifconfig tun1 up */ |
220 | if (priv_set_if_flags(_this->ifname, |
221 | if_flags | IFF_UP0x1 | IFF_MULTICAST0x8000) != 0) { |
222 | npppd_iface_log(_this, LOG_ERR3, |
223 | "enabling %s failed: %m", _this->ifname); |
224 | goto fail; |
225 | } |
226 | /* |
227 | * Add routing entry to communicate from host itself to |
228 | * _this->ip4addr. |
229 | */ |
230 | gw.s_addr = htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ? (__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff ) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001)) ) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001 ))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)( 0x7f000001)))); |
231 | in_host_route_add(&_this->ip4addr, &gw, LOOPBACK_IFNAME"lo0", 0); |
232 | } |
233 | close(sock); sock = -1; |
Value stored to 'sock' is never read | |
234 | |
235 | return 0; |
236 | fail: |
237 | if (sock >= 0) |
238 | close(sock); |
239 | |
240 | return 1; |
241 | } |
242 | |
243 | /** set tunnel end address */ |
244 | int |
245 | npppd_iface_reinit(npppd_iface *_this, struct iface *iface) |
246 | { |
247 | int rval; |
248 | struct in_addr backup; |
249 | char buf0[128], buf1[128]; |
250 | |
251 | _this->ipcpconf = iface->ipcpconf; |
252 | backup = _this->ip4addr; |
253 | _this->ip4addr = iface->ip4addr; |
254 | |
255 | if (_this->using_pppx) |
256 | return 0; |
257 | if ((rval = npppd_iface_setup_ip(_this)) != 0) |
258 | return rval; |
259 | |
260 | if (backup.s_addr != _this->ip4addr.s_addr) { |
261 | npppd_iface_log(_this, LOG_INFO6, "Reinited ip4addr %s=>%s", |
262 | (backup.s_addr != INADDR_ANY((u_int32_t)(0x00000000))) |
263 | ? inet_ntop(AF_INET2, &backup, buf0, sizeof(buf0)) |
264 | : "(not assigned)", |
265 | (_this->ip4addr.s_addr != INADDR_ANY((u_int32_t)(0x00000000))) |
266 | ? inet_ntop(AF_INET2, &_this->ip4addr, buf1, |
267 | sizeof(buf1)) |
268 | : "(not assigned)"); |
269 | } |
270 | |
271 | return 0; |
272 | } |
273 | |
274 | /** start npppd_iface */ |
275 | int |
276 | npppd_iface_start(npppd_iface *_this) |
277 | { |
278 | char buf[PATH_MAX1024]; |
279 | |
280 | NPPPD_IFACE_ASSERT(_this != NULL); |
281 | |
282 | /* open device file */ |
283 | snprintf(buf, sizeof(buf), "/dev/%s", _this->ifname); |
284 | if ((_this->devf = priv_open(buf, O_RDWR0x0002 | O_NONBLOCK0x0004)) < 0) { |
285 | npppd_iface_log(_this, LOG_ERR3, "open(%s) failed: %m", buf); |
286 | goto fail; |
287 | } |
288 | |
289 | event_set(&_this->ev, _this->devf, EV_READ0x02 | EV_PERSIST0x10, |
290 | npppd_iface_io_event_handler, _this); |
291 | event_add(&_this->ev, NULL((void *)0)); |
292 | |
293 | if (_this->using_pppx == 0) { |
294 | if (npppd_iface_setup_ip(_this) != 0) |
295 | goto fail; |
296 | } |
297 | |
298 | #ifndef USE_NPPPD_PIPEX1 |
299 | if (_this->using_pppx) { |
300 | npppd_iface_log(_this, LOG_ERR3, |
301 | "pipex is required when using pppx interface"); |
302 | goto fail; |
303 | } |
304 | #endif /* USE_NPPPD_PIPEX */ |
305 | |
306 | if (_this->using_pppx) { |
307 | npppd_iface_log(_this, LOG_INFO6, "Started pppx"); |
308 | } else { |
309 | npppd_iface_log(_this, LOG_INFO6, "Started ip4addr=%s", |
310 | (npppd_iface_ip_is_ready(_this)((_this)->initialized != 0 && (_this)->ip4addr. s_addr != ((u_int32_t)(0x00000000))))? |
311 | inet_ntop(AF_INET2, &_this->ip4addr, buf, |
312 | sizeof(buf)) : "(not assigned)"); |
313 | } |
314 | _this->started = 1; |
315 | |
316 | return 0; |
317 | fail: |
318 | if (_this->devf >= 0) { |
319 | event_del(&_this->ev); |
320 | close(_this->devf); |
321 | } |
322 | _this->devf = -1; |
323 | |
324 | return -1; |
325 | } |
326 | |
327 | /** stop to use npppd_iface */ |
328 | void |
329 | npppd_iface_stop(npppd_iface *_this) |
330 | { |
331 | struct in_addr gw; |
332 | |
333 | NPPPD_IFACE_ASSERT(_this != NULL); |
334 | if (_this->using_pppx == 0) { |
335 | priv_delete_if_addr(_this->ifname); |
336 | gw.s_addr = htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ? (__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff ) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001)) ) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001 ))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)( 0x7f000001)))); |
337 | in_host_route_delete(&_this->ip4addr, &gw); |
338 | } |
339 | if (_this->devf >= 0) { |
340 | event_del(&_this->ev); |
341 | close(_this->devf); |
342 | npppd_iface_log(_this, LOG_INFO6, "Stopped"); |
343 | } |
344 | _this->devf = -1; |
345 | _this->started = 0; |
346 | event_del(&_this->ev); |
347 | } |
348 | |
349 | /** finalize npppd_iface */ |
350 | void |
351 | npppd_iface_fini(npppd_iface *_this) |
352 | { |
353 | NPPPD_IFACE_ASSERT(_this != NULL); |
354 | _this->initialized = 0; |
355 | } |
356 | |
357 | |
358 | /*********************************************************************** |
359 | * I/O related functions |
360 | ***********************************************************************/ |
361 | /** I/O event handler */ |
362 | static void |
363 | npppd_iface_io_event_handler(int fd, short evtype, void *data) |
364 | { |
365 | int sz; |
366 | u_char buffer[8192]; |
367 | npppd_iface *_this; |
368 | |
369 | NPPPD_IFACE_ASSERT((evtype & EV_READ) != 0); |
370 | |
371 | _this = data; |
372 | NPPPD_IFACE_ASSERT(_this->devf >= 0); |
373 | do { |
374 | sz = read(_this->devf, buffer, sizeof(buffer)); |
375 | if (sz <= 0) { |
376 | if (sz == 0) |
377 | npppd_iface_log(_this, LOG_ERR3, |
378 | "file is closed"); |
379 | else if (errno(*__errno()) == EAGAIN35) |
380 | break; |
381 | else |
382 | npppd_iface_log(_this, LOG_ERR3, |
383 | "read failed: %m"); |
384 | npppd_iface_stop(_this); |
385 | return; |
386 | } |
387 | npppd_iface_network_input(_this, buffer, sz); |
388 | |
389 | } while (1 /* CONSTCOND */); |
390 | |
391 | return; |
392 | } |
393 | |
394 | /** structure of argument of npppd_iface_network_input_delegate */ |
395 | struct npppd_iface_network_input_arg{ |
396 | npppd_iface *_this; |
397 | u_char *pktp; |
398 | int lpktp; |
399 | }; |
400 | |
401 | /** callback function which works for each PPP session */ |
402 | static int |
403 | npppd_iface_network_input_delegate(struct radish *radish, void *args0) |
404 | { |
405 | npppd_ppp *ppp; |
406 | struct sockaddr_npppd *snp; |
407 | struct npppd_iface_network_input_arg *args; |
408 | |
409 | snp = radish->rd_rtent; |
410 | |
411 | if (snp->snp_type == SNP_PPP3) { |
412 | args = args0; |
413 | ppp = snp->snp_data_ptr; |
414 | if (ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx]) != args->_this) |
415 | return 0; |
416 | #ifdef USE_NPPPD_MPPE1 |
417 | if (MPPE_SEND_READY(ppp)((ppp)->mppe_started != 0 && (ppp)->mppe.send.keybits > 0)) { |
418 | /* output via MPPE if MPPE started */ |
419 | mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP0x0021, args->pktp, |
420 | args->lpktp); |
421 | } else if (MPPE_IS_REQUIRED(ppp)(((ppp)->mppe.enabled != 0) && ((ppp)->mppe.required != 0))) { |
422 | /* in case MPPE not started but MPPE is mandatory, */ |
423 | /* it is not necessary to log because of multicast. */ |
424 | return 0; |
425 | } |
426 | #endif |
427 | ppp_output(ppp, PPP_PROTO_IP0x0021, 0, 0, args->pktp, args->lpktp); |
428 | } |
429 | |
430 | return 0; |
431 | } |
432 | |
433 | static void |
434 | npppd_iface_network_input_ipv4(npppd_iface *_this, struct pppx_hdr *pppx, |
435 | u_char *pktp, int lpktp) |
436 | { |
437 | struct ip *iphdr; |
438 | npppd *_npppd; |
439 | npppd_ppp *ppp; |
440 | struct npppd_iface_network_input_arg input_arg; |
441 | |
442 | NPPPD_IFACE_ASSERT(_this != NULL); |
443 | NPPPD_IFACE_ASSERT(pktp != NULL); |
444 | |
445 | iphdr = (struct ip *)pktp; |
446 | _npppd = _this->npppd; |
447 | |
448 | if (lpktp < sizeof(iphdr)) { |
449 | npppd_iface_log(_this, LOG_ERR3, "Received short packet."); |
450 | return; |
451 | } |
452 | if (_this->using_pppx) |
453 | ppp = npppd_get_ppp_by_id(_npppd, pppx->pppx_id); |
454 | else { |
455 | if (IN_MULTICAST(ntohl(iphdr->ip_dst.s_addr))(((u_int32_t)((__uint32_t)(__builtin_constant_p(iphdr->ip_dst .s_addr) ? (__uint32_t)(((__uint32_t)(iphdr->ip_dst.s_addr ) & 0xff) << 24 | ((__uint32_t)(iphdr->ip_dst.s_addr ) & 0xff00) << 8 | ((__uint32_t)(iphdr->ip_dst.s_addr ) & 0xff0000) >> 8 | ((__uint32_t)(iphdr->ip_dst .s_addr) & 0xff000000) >> 24) : __swap32md(iphdr-> ip_dst.s_addr))) & ((u_int32_t)(0xf0000000))) == ((u_int32_t )(0xe0000000)))) { |
456 | NPPPD_IFACE_ASSERT( |
457 | ((npppd *)(_this->npppd))->rd != NULL); |
458 | input_arg._this = _this; |
459 | input_arg.pktp = pktp; |
460 | input_arg.lpktp = lpktp; |
461 | /* delegate */ |
462 | rd_walktree(((npppd *)(_this->npppd))->rd, |
463 | npppd_iface_network_input_delegate, &input_arg); |
464 | return; |
465 | } |
466 | ppp = npppd_get_ppp_by_ip(_npppd, iphdr->ip_dst); |
467 | } |
468 | |
469 | if (ppp == NULL((void *)0)) { |
470 | #ifdef NPPPD_DEBUG |
471 | log_printf(LOG_INFO6, "%s received a packet to unknown " |
472 | "%s.", _this->ifname, inet_ntoa(iphdr->ip_dst)); |
473 | #endif |
474 | return; |
475 | } |
476 | #ifndef NO_ADJUST_MSS |
477 | if (ppp->adjust_mss) { |
478 | adjust_tcp_mss(pktp, lpktp, MRU_IPMTU(ppp->peer_mru)(ppp->peer_mru)); |
479 | } |
480 | #endif |
481 | if (ppp->timeout_sec > 0 && !ip_is_idle_packet(iphdr, lpktp)) |
482 | ppp_reset_idle_timeout(ppp); |
483 | |
484 | #ifdef USE_NPPPD_MPPE1 |
485 | if (MPPE_SEND_READY(ppp)((ppp)->mppe_started != 0 && (ppp)->mppe.send.keybits > 0)) { |
486 | /* output via MPPE if MPPE started */ |
487 | mppe_pkt_output(&ppp->mppe, PPP_PROTO_IP0x0021, pktp, lpktp); |
488 | return; |
489 | } else if (MPPE_IS_REQUIRED(ppp)(((ppp)->mppe.enabled != 0) && ((ppp)->mppe.required != 0))) { |
490 | /* in case MPPE not started but MPPE is mandatory */ |
491 | ppp_log(ppp, LOG_WARNING4, "A packet received from network, " |
492 | "but MPPE is not started."); |
493 | return; |
494 | } |
495 | #endif |
496 | ppp_output(ppp, PPP_PROTO_IP0x0021, 0, 0, pktp, lpktp); |
497 | } |
498 | |
499 | /** |
500 | * This function is called when an input packet come from network(tun). |
501 | * Currently, it assumes that it input IPv4 packet. |
502 | */ |
503 | static void |
504 | npppd_iface_network_input(npppd_iface *_this, u_char *pktp, int lpktp) |
505 | { |
506 | uint32_t af; |
507 | struct pppx_hdr *pppx = NULL((void *)0); |
508 | |
509 | if (_this->using_pppx) { |
510 | if (lpktp < sizeof(struct pppx_hdr)) { |
511 | npppd_iface_log(_this, LOG_ERR3, |
512 | "Received short packet."); |
513 | return; |
514 | } |
515 | pppx = (struct pppx_hdr *)pktp; |
516 | pktp += sizeof(struct pppx_hdr); |
517 | lpktp -= sizeof(struct pppx_hdr); |
518 | } |
519 | |
520 | if (lpktp < sizeof(uint32_t)) { |
521 | npppd_iface_log(_this, LOG_ERR3, "Received short packet."); |
522 | return; |
523 | } |
524 | GETLONG(af, pktp){ (af) = *(pktp)++ << 8; (af) |= *(pktp)++; (af) <<= 8; (af) |= *(pktp)++; (af) <<= 8; (af) |= *(pktp)++; }; |
525 | lpktp -= sizeof(uint32_t); |
526 | |
527 | switch (af) { |
528 | case AF_INET2: |
529 | npppd_iface_network_input_ipv4(_this, pppx, pktp, lpktp); |
530 | break; |
531 | |
532 | default: |
533 | NPPPD_IFACE_ASSERT(0); |
534 | break; |
535 | |
536 | } |
537 | } |
538 | |
539 | /** write to tunnel device */ |
540 | void |
541 | npppd_iface_write(npppd_iface *_this, npppd_ppp *ppp, int proto, u_char *pktp, |
542 | int lpktp) |
543 | { |
544 | int niov = 0, tlen; |
545 | uint32_t th; |
546 | struct iovec iov[3]; |
547 | struct pppx_hdr pppx; |
548 | NPPPD_IFACE_ASSERT(_this != NULL); |
549 | NPPPD_IFACE_ASSERT(_this->devf >= 0); |
550 | |
551 | tlen = 0; |
552 | th = htonl(proto)(__uint32_t)(__builtin_constant_p(proto) ? (__uint32_t)(((__uint32_t )(proto) & 0xff) << 24 | ((__uint32_t)(proto) & 0xff00) << 8 | ((__uint32_t)(proto) & 0xff0000) >> 8 | ((__uint32_t)(proto) & 0xff000000) >> 24) : __swap32md (proto)); |
553 | if (_this->using_pppx) { |
554 | pppx.pppx_proto = npppd_pipex_proto(ppp->tunnel_type)(((ppp->tunnel_type) == 1)? 1 : ((ppp->tunnel_type) == 2 )? 2 : ((ppp->tunnel_type) == 3)? 3 : -1); |
555 | pppx.pppx_id = ppp->tunnel_session_id; |
556 | iov[niov].iov_base = &pppx; |
557 | iov[niov++].iov_len = sizeof(pppx); |
558 | tlen += sizeof(pppx); |
559 | } |
560 | iov[niov].iov_base = &th; |
561 | iov[niov++].iov_len = sizeof(th); |
562 | tlen += sizeof(th); |
563 | iov[niov].iov_base = pktp; |
564 | iov[niov++].iov_len = lpktp; |
565 | tlen += lpktp; |
566 | |
567 | if (writev(_this->devf, iov, niov) != tlen) |
568 | npppd_iface_log(_this, LOG_ERR3, "write failed: %m"); |
569 | } |
570 | |
571 | /*********************************************************************** |
572 | * misc functions |
573 | ***********************************************************************/ |
574 | /** Log it which starts the label based on this instance. */ |
575 | static int |
576 | npppd_iface_log(npppd_iface *_this, int prio, const char *fmt, ...) |
577 | { |
578 | int status; |
579 | char logbuf[BUFSIZ1024]; |
580 | va_list ap; |
581 | |
582 | NPPPD_IFACE_ASSERT(_this != NULL); |
583 | |
584 | va_start(ap, fmt)__builtin_va_start(ap, fmt); |
585 | snprintf(logbuf, sizeof(logbuf), "%s %s", _this->ifname, fmt); |
586 | status = vlog_printf(prio, logbuf, ap); |
587 | va_end(ap)__builtin_va_end(ap); |
588 | |
589 | return status; |
590 | } |