xref: /openbsd-src/sys/net/pipex.c (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
1 /*	$OpenBSD: pipex.c,v 1.135 2021/07/27 09:29:09 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 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/mbuf.h>
32 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <sys/select.h>
35 #include <sys/sysctl.h>
36 #include <sys/syslog.h>
37 #include <sys/conf.h>
38 #include <sys/time.h>
39 #include <sys/timeout.h>
40 #include <sys/kernel.h>
41 #include <sys/pool.h>
42 #include <sys/percpu.h>
43 
44 #include <net/if.h>
45 #include <net/if_types.h>
46 #include <netinet/in.h>
47 #include <netinet/if_ether.h>
48 #include <net/if_dl.h>
49 
50 #include <net/radix.h>
51 #include <net/route.h>
52 #include <net/ppp_defs.h>
53 #include <net/ppp-comp.h>
54 
55 #include "pf.h"
56 #if NPF > 0
57 #include <net/pfvar.h>
58 #endif
59 
60 #include "bpfilter.h"
61 #if NBPFILTER > 0
62 #include <net/bpf.h>
63 #endif
64 
65 #include <netinet/ip.h>
66 #include <netinet/ip_var.h>
67 #ifdef INET6
68 #include <netinet/ip6.h>
69 #include <netinet6/ip6_var.h>
70 #endif
71 #include <netinet/tcp.h>
72 #include <netinet/udp.h>
73 #include <netinet/udp_var.h>
74 #include <crypto/arc4.h>
75 
76 /* drop static for ddb debuggability */
77 #define	Static
78 
79 #include <net/pipex.h>
80 #include "pipex_local.h"
81 
82 struct pool pipex_session_pool;
83 struct pool mppe_key_pool;
84 
85 /*
86  * Global data
87  * Locks used to protect global data
88  *       A       atomic operation
89  *       I       immutable after creation
90  *       N       net lock
91  */
92 
93 int	pipex_enable = 0;			/* [N] */
94 struct pipex_hash_head
95     pipex_session_list,				/* [N] master session list */
96     pipex_close_wait_list,			/* [N] expired session list */
97     pipex_peer_addr_hashtable[PIPEX_HASH_SIZE],	/* [N] peer's address hash */
98     pipex_id_hashtable[PIPEX_HASH_SIZE];	/* [N] peer id hash */
99 
100 struct radix_node_head	*pipex_rd_head4 = NULL;	/* [N] */
101 struct radix_node_head	*pipex_rd_head6 = NULL;	/* [N] */
102 struct timeout pipex_timer_ch;		/* callout timer context */
103 int pipex_prune = 1;			/* [I] walk list every seconds */
104 
105 /* borrow an mbuf pkthdr field */
106 #define ph_ppp_proto ether_vtag
107 
108 #ifdef PIPEX_DEBUG
109 int pipex_debug = 0;		/* [A] systcl net.inet.ip.pipex_debug */
110 #endif
111 
112 /* PPP compression == MPPE is assumed, so don't answer CCP Reset-Request. */
113 #define PIPEX_NO_CCP_RESETACK	1
114 
115 /************************************************************************
116  * Core functions
117  ************************************************************************/
118 void
119 pipex_init(void)
120 {
121 	int		 i;
122 	static int	 pipex_init_done = 0;
123 
124 	if (pipex_init_done++)
125 		return;
126 
127 	rn_init(sizeof(struct sockaddr_in6));
128 
129 	pool_init(&pipex_session_pool, sizeof(struct pipex_session), 0,
130 	    IPL_SOFTNET, PR_WAITOK, "ppxss", NULL);
131 	pool_init(&mppe_key_pool, PIPEX_MPPE_KEYLEN * PIPEX_MPPE_NOLDKEY, 0,
132 	    IPL_SOFTNET, PR_WAITOK, "mppekey", NULL);
133 
134 	LIST_INIT(&pipex_session_list);
135 	LIST_INIT(&pipex_close_wait_list);
136 
137 	for (i = 0; i < nitems(pipex_id_hashtable); i++)
138 		LIST_INIT(&pipex_id_hashtable[i]);
139 	for (i = 0; i < nitems(pipex_peer_addr_hashtable); i++)
140 		LIST_INIT(&pipex_peer_addr_hashtable[i]);
141 }
142 
143 void
144 pipex_destroy_all_sessions(void *ownersc)
145 {
146 	struct pipex_session *session, *session_tmp;
147 
148 	NET_ASSERT_LOCKED();
149 
150 	LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
151 	    session_tmp) {
152 		if (session->ownersc == ownersc) {
153 			KASSERT(session->is_pppx == 0);
154 			pipex_unlink_session(session);
155 			pipex_rele_session(session);
156 		}
157 	}
158 }
159 
160 int
161 pipex_ioctl(void *ownersc, u_long cmd, caddr_t data)
162 {
163 	int ret = 0;
164 
165 	NET_ASSERT_LOCKED();
166 	switch (cmd) {
167 	case PIPEXCSESSION:
168 		ret = pipex_config_session(
169 		    (struct pipex_session_config_req *)data, ownersc);
170 		break;
171 
172 	case PIPEXGSTAT:
173 		ret = pipex_get_stat((struct pipex_session_stat_req *)data,
174 		    ownersc);
175 		break;
176 
177 	case PIPEXGCLOSED:
178 		ret = pipex_get_closed((struct pipex_session_list_req *)data,
179 		    ownersc);
180 		break;
181 
182 	default:
183 		ret = ENOTTY;
184 		break;
185 	}
186 
187 	return (ret);
188 }
189 
190 /************************************************************************
191  * Session management functions
192  ************************************************************************/
193 int
194 pipex_init_session(struct pipex_session **rsession,
195     struct pipex_session_req *req)
196 {
197 	struct pipex_session *session;
198 #ifdef PIPEX_PPPOE
199 	struct ifnet *over_ifp = NULL;
200 #endif
201 
202 	/* Checks requeted parameters.  */
203 	switch (req->pr_protocol) {
204 #ifdef PIPEX_PPPOE
205 	case PIPEX_PROTO_PPPOE:
206 		if (req->pr_peer_address.ss_family != AF_UNSPEC)
207 			return (EINVAL);
208 		break;
209 #endif
210 #if defined(PIPEX_L2TP) || defined(PIPEX_PPTP)
211 	case PIPEX_PROTO_PPTP:
212 	case PIPEX_PROTO_L2TP:
213 		switch (req->pr_peer_address.ss_family) {
214 		case AF_INET:
215 			if (req->pr_peer_address.ss_len !=
216 			    sizeof(struct sockaddr_in))
217 				return (EINVAL);
218 			break;
219 #ifdef INET6
220 		case AF_INET6:
221 			if (req->pr_peer_address.ss_len !=
222 			    sizeof(struct sockaddr_in6))
223 				return (EINVAL);
224 			break;
225 #endif
226 		default:
227 			return (EPROTONOSUPPORT);
228 		}
229 		if (req->pr_peer_address.ss_family !=
230 		    req->pr_local_address.ss_family ||
231 		    req->pr_peer_address.ss_len !=
232 		    req->pr_local_address.ss_len)
233 			return (EINVAL);
234 		break;
235 #endif /* defined(PIPEX_PPTP) || defined(PIPEX_L2TP) */
236 	default:
237 		return (EPROTONOSUPPORT);
238 	}
239 #ifdef PIPEX_MPPE
240 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) {
241 		if (req->pr_mppe_recv.keylenbits <= 0)
242 			return (EINVAL);
243 	}
244 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) {
245 		if (req->pr_mppe_send.keylenbits <= 0)
246 			return (EINVAL);
247 	}
248 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_REQUIRED) != 0) {
249 		if ((req->pr_ppp_flags &
250 		    (PIPEX_PPP_MPPE_ACCEPTED | PIPEX_PPP_MPPE_ENABLED)) !=
251 		    (PIPEX_PPP_MPPE_ACCEPTED | PIPEX_PPP_MPPE_ENABLED))
252 			return (EINVAL);
253 	}
254 #endif
255 
256 #ifdef PIPEX_PPPOE
257 	if (req->pr_protocol == PIPEX_PROTO_PPPOE) {
258 		over_ifp = if_unit(req->pr_proto.pppoe.over_ifname);
259 		if (over_ifp == NULL)
260 			return (EINVAL);
261 	}
262 #endif
263 
264 	/* prepare a new session */
265 	session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
266 	mtx_init(&session->pxs_mtx, IPL_SOFTNET);
267 	session->state = PIPEX_STATE_INITIAL;
268 	session->protocol = req->pr_protocol;
269 	session->session_id = req->pr_session_id;
270 	session->peer_session_id = req->pr_peer_session_id;
271 	session->peer_mru = req->pr_peer_mru;
272 	session->timeout_sec = req->pr_timeout_sec;
273 	session->ppp_flags = req->pr_ppp_flags;
274 	session->ppp_id = req->pr_ppp_id;
275 
276 	session->ip_forward = 1;
277 
278 	session->stat_counters = counters_alloc(pxc_ncounters);
279 
280 	session->ip_address.sin_family = AF_INET;
281 	session->ip_address.sin_len = sizeof(struct sockaddr_in);
282 	session->ip_address.sin_addr = req->pr_ip_address;
283 
284 	session->ip_netmask.sin_family = AF_INET;
285 	session->ip_netmask.sin_len = sizeof(struct sockaddr_in);
286 	session->ip_netmask.sin_addr = req->pr_ip_netmask;
287 
288 	if (session->ip_netmask.sin_addr.s_addr == 0L)
289 		session->ip_netmask.sin_addr.s_addr = 0xffffffffL;
290 	session->ip_address.sin_addr.s_addr &=
291 	    session->ip_netmask.sin_addr.s_addr;
292 
293 	if (req->pr_peer_address.ss_len > 0)
294 		memcpy(&session->peer, &req->pr_peer_address,
295 		    MIN(req->pr_peer_address.ss_len, sizeof(session->peer)));
296 	if (req->pr_local_address.ss_len > 0)
297 		memcpy(&session->local, &req->pr_local_address,
298 		    MIN(req->pr_local_address.ss_len, sizeof(session->local)));
299 #ifdef PIPEX_PPPOE
300 	if (req->pr_protocol == PIPEX_PROTO_PPPOE) {
301 		session->proto.pppoe.over_ifidx = over_ifp->if_index;
302 		if_put(over_ifp);
303 	}
304 #endif
305 #ifdef PIPEX_PPTP
306 	if (req->pr_protocol == PIPEX_PROTO_PPTP) {
307 		struct pipex_pptp_session *sess_pptp = &session->proto.pptp;
308 
309 		sess_pptp->snd_gap = 0;
310 		sess_pptp->rcv_gap = 0;
311 		sess_pptp->snd_una = req->pr_proto.pptp.snd_una;
312 		sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt;
313 		sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt;
314 		sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked;
315 
316 		sess_pptp->winsz = req->pr_proto.pptp.winsz;
317 		sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz;
318 		sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz;
319 		/* last ack number */
320 		sess_pptp->ul_snd_una = sess_pptp->snd_una - 1;
321 	}
322 #endif
323 #ifdef PIPEX_L2TP
324 	if (req->pr_protocol == PIPEX_PROTO_L2TP) {
325 		struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp;
326 
327 		/* session keys */
328 		sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id;
329 		sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id;
330 
331 		/* protocol options */
332 		sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags;
333 
334 		/* initial state of dynamic context */
335 		sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0;
336 		sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt;
337 		sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt;
338 		sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una;
339 		sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked;
340 		/* last ack number */
341 		sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1;
342 		sess_l2tp->ipsecflowinfo = req->pr_proto.l2tp.ipsecflowinfo;
343 	}
344 #endif
345 #ifdef PIPEX_MPPE
346 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) {
347 		pipex_session_init_mppe_recv(session,
348 		    req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits,
349 		    req->pr_mppe_recv.master_key);
350 	}
351 	if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) {
352 		pipex_session_init_mppe_send(session,
353 		    req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits,
354 		    req->pr_mppe_send.master_key);
355 	}
356 #endif
357 
358 	*rsession = session;
359 
360 	return 0;
361 }
362 
363 void
364 pipex_rele_session(struct pipex_session *session)
365 {
366 	if (session->mppe_recv.old_session_keys)
367 		pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys);
368 	counters_free(session->stat_counters, pxc_ncounters);
369 	pool_put(&pipex_session_pool, session);
370 }
371 
372 int
373 pipex_link_session(struct pipex_session *session, struct ifnet *ifp,
374     void *ownersc)
375 {
376 	struct pipex_hash_head *chain;
377 	struct radix_node *rn;
378 
379 	NET_ASSERT_LOCKED();
380 
381 	if (pipex_rd_head4 == NULL) {
382 		if (!rn_inithead((void **)&pipex_rd_head4,
383 		    offsetof(struct sockaddr_in, sin_addr)))
384 			panic("rn_inithead() failed on pipex_link_session()");
385 	}
386 	if (pipex_rd_head6 == NULL) {
387 		if (!rn_inithead((void **)&pipex_rd_head6,
388 		    offsetof(struct sockaddr_in6, sin6_addr)))
389 			panic("rn_inithead() failed on pipex_link_session()");
390 	}
391 	if (pipex_lookup_by_session_id(session->protocol,
392 	    session->session_id))
393 		return (EEXIST);
394 
395 	session->ownersc = ownersc;
396 	session->ifindex = ifp->if_index;
397 	if (ifp->if_flags & IFF_POINTOPOINT)
398 		session->is_pppx = 1;
399 
400 	if (session->is_pppx == 0 &&
401 	    !in_nullhost(session->ip_address.sin_addr)) {
402 		if (pipex_lookup_by_ip_address(session->ip_address.sin_addr)
403 		    != NULL)
404 			return (EADDRINUSE);
405 		rn = rn_addroute(&session->ip_address, &session->ip_netmask,
406 		    pipex_rd_head4, session->ps4_rn, RTP_STATIC);
407 		if (rn == NULL)
408 			return (ENOMEM);
409 	}
410 
411 	LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
412 	chain = PIPEX_ID_HASHTABLE(session->session_id);
413 	LIST_INSERT_HEAD(chain, session, id_chain);
414 #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
415 	switch (session->protocol) {
416 	case PIPEX_PROTO_PPTP:
417 	case PIPEX_PROTO_L2TP:
418 		chain = PIPEX_PEER_ADDR_HASHTABLE(
419 		    pipex_sockaddr_hash_key(&session->peer.sa));
420 		LIST_INSERT_HEAD(chain, session, peer_addr_chain);
421 	}
422 #endif
423 
424 	/* if first session is added, start timer */
425 	if (LIST_NEXT(session, session_list) == NULL)
426 		pipex_timer_start();
427 	session->state = PIPEX_STATE_OPENED;
428 
429 	return (0);
430 }
431 
432 void
433 pipex_unlink_session(struct pipex_session *session)
434 {
435 	struct radix_node *rn;
436 
437 	session->ifindex = 0;
438 
439 	NET_ASSERT_LOCKED();
440 	if (session->state == PIPEX_STATE_CLOSED)
441 		return;
442 	if (session->is_pppx == 0 &&
443 	    !in_nullhost(session->ip_address.sin_addr)) {
444 		KASSERT(pipex_rd_head4 != NULL);
445 		rn = rn_delete(&session->ip_address, &session->ip_netmask,
446 		    pipex_rd_head4, (struct radix_node *)session);
447 		KASSERT(rn != NULL);
448 	}
449 
450 	LIST_REMOVE(session, id_chain);
451 #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
452 	switch (session->protocol) {
453 	case PIPEX_PROTO_PPTP:
454 	case PIPEX_PROTO_L2TP:
455 		LIST_REMOVE(session, peer_addr_chain);
456 		break;
457 	}
458 #endif
459 	if (session->state == PIPEX_STATE_CLOSE_WAIT)
460 		LIST_REMOVE(session, state_list);
461 	LIST_REMOVE(session, session_list);
462 	session->state = PIPEX_STATE_CLOSED;
463 
464 	/* if final session is destroyed, stop timer */
465 	if (LIST_EMPTY(&pipex_session_list))
466 		pipex_timer_stop();
467 }
468 
469 int
470 pipex_notify_close_session(struct pipex_session *session)
471 {
472 	NET_ASSERT_LOCKED();
473 	session->state = PIPEX_STATE_CLOSE_WAIT;
474 	session->idle_time = 0;
475 	LIST_INSERT_HEAD(&pipex_close_wait_list, session, state_list);
476 
477 	return (0);
478 }
479 
480 void
481 pipex_export_session_stats(struct pipex_session *session,
482     struct pipex_statistics *stats)
483 {
484 	uint64_t counters[pxc_ncounters];
485 
486 	memset(stats, 0, sizeof(*stats));
487 
488 	counters_read(session->stat_counters, counters, pxc_ncounters);
489 	stats->ipackets = counters[pxc_ipackets];
490 	stats->ierrors = counters[pxc_ierrors];
491 	stats->ibytes = counters[pxc_ibytes];
492 	stats->opackets = counters[pxc_opackets];
493 	stats->oerrors = counters[pxc_oerrors];
494 	stats->obytes = counters[pxc_obytes];
495 	stats->idle_time = session->idle_time;
496 }
497 
498 Static int
499 pipex_config_session(struct pipex_session_config_req *req, void *ownersc)
500 {
501 	struct pipex_session *session;
502 
503 	NET_ASSERT_LOCKED();
504 	session = pipex_lookup_by_session_id(req->pcr_protocol,
505 	    req->pcr_session_id);
506 	if (session == NULL)
507 		return (EINVAL);
508 	if (session->ownersc != ownersc)
509 		return (EINVAL);
510 	session->ip_forward = req->pcr_ip_forward;
511 
512 	return (0);
513 }
514 
515 Static int
516 pipex_get_stat(struct pipex_session_stat_req *req, void *ownersc)
517 {
518 	struct pipex_session *session;
519 
520 	NET_ASSERT_LOCKED();
521 	session = pipex_lookup_by_session_id(req->psr_protocol,
522 	    req->psr_session_id);
523 	if (session == NULL)
524 		return (EINVAL);
525 	if (session->ownersc != ownersc)
526 		return (EINVAL);
527 	pipex_export_session_stats(session, &req->psr_stat);
528 
529 	return (0);
530 }
531 
532 Static int
533 pipex_get_closed(struct pipex_session_list_req *req, void *ownersc)
534 {
535 	struct pipex_session *session, *session_tmp;
536 
537 	NET_ASSERT_LOCKED();
538 	bzero(req, sizeof(*req));
539 	LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list,
540 	    session_tmp) {
541 		if (session->ownersc != ownersc)
542 			continue;
543 		req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id;
544 		LIST_REMOVE(session, state_list);
545 		session->state = PIPEX_STATE_CLOSE_WAIT2;
546 		if (req->plr_ppp_id_count >= PIPEX_MAX_LISTREQ) {
547 			if (!LIST_EMPTY(&pipex_close_wait_list))
548 				req->plr_flags |= PIPEX_LISTREQ_MORE;
549 			break;
550 		}
551 	}
552 
553 	return (0);
554 }
555 
556 Static struct pipex_session *
557 pipex_lookup_by_ip_address(struct in_addr addr)
558 {
559 	struct pipex_session *session;
560 	struct sockaddr_in pipex_in4, pipex_in4mask;
561 
562 	if (pipex_rd_head4 == NULL)
563 		return (NULL);
564 	bzero(&pipex_in4, sizeof(pipex_in4));
565 	pipex_in4.sin_addr = addr;
566 	pipex_in4.sin_family = AF_INET;
567 	pipex_in4.sin_len = sizeof(pipex_in4);
568 
569 	bzero(&pipex_in4mask, sizeof(pipex_in4mask));
570 	pipex_in4mask.sin_addr.s_addr = htonl(0xFFFFFFFFL);
571 	pipex_in4mask.sin_family = AF_INET;
572 	pipex_in4mask.sin_len = sizeof(pipex_in4mask);
573 
574 	session = (struct pipex_session *)rn_lookup(&pipex_in4, &pipex_in4mask,
575 	    pipex_rd_head4);
576 
577 #ifdef PIPEX_DEBUG
578 	if (session == NULL) {
579 		char buf[INET_ADDRSTRLEN];
580 
581 		PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (addr=%s)",
582 		    __func__, inet_ntop(AF_INET, &addr, buf, sizeof(buf))));
583 	}
584 #endif
585 
586 	return (session);
587 }
588 
589 Static struct pipex_session *
590 pipex_lookup_by_session_id(int protocol, int session_id)
591 {
592 	struct pipex_hash_head *list;
593 	struct pipex_session *session;
594 
595 	NET_ASSERT_LOCKED();
596 	list = PIPEX_ID_HASHTABLE(session_id);
597 	LIST_FOREACH(session, list, id_chain) {
598 		if (session->protocol == protocol &&
599 		    session->session_id == session_id)
600 			break;
601 	}
602 
603 #ifdef PIPEX_DEBUG
604 	if (session == NULL)
605 		PIPEX_DBG((NULL, LOG_DEBUG,
606 		    "<%s> session not found (session_id=%d)", __func__,
607 		    session_id));
608 #endif
609 
610 	return (session);
611 }
612 
613 /***********************************************************************
614  * Timer functions
615  ***********************************************************************/
616 Static void
617 pipex_timer_start(void)
618 {
619 	timeout_set_proc(&pipex_timer_ch, pipex_timer, NULL);
620 	timeout_add_sec(&pipex_timer_ch, pipex_prune);
621 }
622 
623 Static void
624 pipex_timer_stop(void)
625 {
626 	timeout_del(&pipex_timer_ch);
627 }
628 
629 Static void
630 pipex_timer(void *ignored_arg)
631 {
632 	struct pipex_session *session, *session_tmp;
633 
634 	timeout_add_sec(&pipex_timer_ch, pipex_prune);
635 
636 	NET_LOCK();
637 	/* walk through */
638 	LIST_FOREACH_SAFE(session, &pipex_session_list, session_list,
639 	    session_tmp) {
640 		switch (session->state) {
641 		case PIPEX_STATE_OPENED:
642 			if (session->timeout_sec == 0)
643 				continue;
644 
645 			session->idle_time++;
646 			if (session->idle_time < session->timeout_sec)
647 				continue;
648 
649 			pipex_notify_close_session(session);
650 			break;
651 
652 		case PIPEX_STATE_CLOSE_WAIT:
653 		case PIPEX_STATE_CLOSE_WAIT2:
654 			/* Waiting PIPEXDSESSION from userland */
655 			session->idle_time++;
656 			if (session->idle_time < PIPEX_CLOSE_TIMEOUT)
657 				continue;
658 			/* Release the sessions when timeout */
659 			pipex_unlink_session(session);
660 			KASSERTMSG(session->is_pppx == 0,
661 			    "FIXME session must not be released when pppx");
662 			pipex_rele_session(session);
663 			break;
664 
665 		default:
666 			break;
667 		}
668 	}
669 
670 	NET_UNLOCK();
671 }
672 
673 /***********************************************************************
674  * Common network I/O functions.  (tunnel protocol independent)
675  ***********************************************************************/
676 Static void
677 pipex_ip_output(struct mbuf *m0, struct pipex_session *session)
678 {
679 	int is_idle;
680 
681 	if (session->is_multicast == 0) {
682 		/*
683 		 * Multicast packet is a idle packet and it's not TCP.
684 		 */
685 		if (session->ip_forward == 0 && session->ip6_forward == 0)
686 			goto drop;
687 		/* reset idle timer */
688 		if (session->timeout_sec != 0) {
689 			is_idle = 0;
690 			m0 = ip_is_idle_packet(m0, &is_idle);
691 			if (m0 == NULL)
692 				goto dropped;
693 			if (is_idle == 0)
694 				/* update expire time */
695 				session->idle_time = 0;
696 		}
697 
698 		/* adjust tcpmss */
699 		if ((session->ppp_flags & PIPEX_PPP_ADJUST_TCPMSS) != 0) {
700 			m0 = adjust_tcp_mss(m0, session->peer_mru);
701 			if (m0 == NULL)
702 				goto dropped;
703 		}
704 
705 		pipex_ppp_output(m0, session, PPP_IP);
706 	} else {
707 		struct pipex_session *session_tmp;
708 		struct mbuf *m;
709 
710 		m0->m_flags &= ~(M_BCAST|M_MCAST);
711 
712 		LIST_FOREACH(session_tmp, &pipex_session_list, session_list) {
713 			if (session_tmp->ownersc != session->ownersc)
714 				continue;
715 			if (session_tmp->ip_forward == 0 &&
716 			    session_tmp->ip6_forward == 0)
717 				continue;
718 			m = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
719 			if (m == NULL) {
720 				counters_inc(session->stat_counters,
721 				    pxc_oerrors);
722 				continue;
723 			}
724 			pipex_ppp_output(m, session_tmp, PPP_IP);
725 		}
726 		m_freem(m0);
727 	}
728 
729 	return;
730 drop:
731 	m_freem(m0);
732 dropped:
733 	counters_inc(session->stat_counters, pxc_oerrors);
734 }
735 
736 Static void
737 pipex_ppp_output(struct mbuf *m0, struct pipex_session *session, int proto)
738 {
739 	u_char *cp, hdr[16];
740 
741 	NET_ASSERT_LOCKED();
742 
743 #ifdef PIPEX_MPPE
744 	if (pipex_session_is_mppe_enabled(session)) {
745 		if (proto == PPP_IP) {
746 			pipex_mppe_output(m0, session, PPP_IP);
747 			return;
748 		}
749 	}
750 #endif /* PIPEX_MPPE */
751 	cp = hdr;
752 	if (session->protocol != PIPEX_PROTO_PPPOE) {
753 		/* PPPoE has not address and control field */
754 		PUTCHAR(PPP_ALLSTATIONS, cp);
755 		PUTCHAR(PPP_UI, cp);
756 	}
757 	PUTSHORT(proto, cp);
758 
759 	M_PREPEND(m0, cp - hdr, M_NOWAIT);
760 	if (m0 == NULL)
761 		goto drop;
762 	memcpy(mtod(m0, u_char *), hdr, cp - hdr);
763 
764 	switch (session->protocol) {
765 #ifdef	PIPEX_PPPOE
766 	case PIPEX_PROTO_PPPOE:
767 		pipex_pppoe_output(m0, session);
768 		break;
769 #endif
770 #ifdef PIPEX_PPTP
771 	case PIPEX_PROTO_PPTP:
772 		pipex_pptp_output(m0, session, 1, 1);
773 		break;
774 #endif
775 #ifdef	PIPEX_L2TP
776 	case PIPEX_PROTO_L2TP:
777 		pipex_l2tp_output(m0, session);
778 		break;
779 #endif
780 	default:
781 		goto drop;
782 	}
783 
784 	return;
785 drop:
786 	m_freem(m0);
787 	counters_inc(session->stat_counters, pxc_oerrors);
788 }
789 
790 Static void
791 pipex_ppp_input(struct mbuf *m0, struct pipex_session *session, int decrypted)
792 {
793 	int proto, hlen = 0;
794 	struct mbuf *n;
795 
796 	KASSERT(m0->m_pkthdr.len >= PIPEX_PPPMINLEN);
797 	proto = pipex_ppp_proto(m0, session, 0, &hlen);
798 #ifdef PIPEX_MPPE
799 	if (proto == PPP_COMP) {
800 		if (decrypted)
801 			goto drop;
802 
803 		/* checked this on ppp_common_input() already. */
804 		KASSERT(pipex_session_is_mppe_accepted(session));
805 
806 		m_adj(m0, hlen);
807 		pipex_mppe_input(m0, session);
808 		return;
809 	}
810 	if (proto == PPP_CCP) {
811 		if (decrypted)
812 			goto drop;
813 
814 #if NBPFILTER > 0
815 	    {
816 		struct ifnet *ifp;
817 
818 		if ((ifp = if_get(session->ifindex)) != NULL) {
819 			if (ifp->if_bpf && ifp->if_type == IFT_PPP)
820 				bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_IN);
821 		}
822 		if_put(ifp);
823 	    }
824 #endif
825 		m_adj(m0, hlen);
826 		pipex_ccp_input(m0, session);
827 		return;
828 	}
829 #endif
830 	m_adj(m0, hlen);
831 	if (!ALIGNED_POINTER(mtod(m0, caddr_t), uint32_t)) {
832 		n = m_dup_pkt(m0, 0, M_NOWAIT);
833 		if (n == NULL)
834 			goto drop;
835 		m_freem(m0);
836 		m0 = n;
837 	}
838 
839 	switch (proto) {
840 	case PPP_IP:
841 		if (session->ip_forward == 0)
842 			goto drop;
843 		if (!decrypted && pipex_session_is_mppe_required(session))
844 			/*
845 			 * if ip packet received when mppe
846 			 * is required, discard it.
847 			 */
848 			goto drop;
849 		pipex_ip_input(m0, session);
850 		return;
851 #ifdef INET6
852 	case PPP_IPV6:
853 		if (session->ip6_forward == 0)
854 			goto drop;
855 		if (!decrypted && pipex_session_is_mppe_required(session))
856 			/*
857 			 * if ip packet received when mppe
858 			 * is required, discard it.
859 			 */
860 			goto drop;
861 		pipex_ip6_input(m0, session);
862 		return;
863 #endif
864 	default:
865 		if (decrypted)
866 			goto drop;
867 		/* protocol must be checked on pipex_common_input() already */
868 		KASSERT(0);
869 		goto drop;
870 	}
871 
872 	return;
873 drop:
874 	m_freem(m0);
875 	counters_inc(session->stat_counters, pxc_ierrors);
876 }
877 
878 Static void
879 pipex_ip_input(struct mbuf *m0, struct pipex_session *session)
880 {
881 	struct ifnet *ifp;
882 	struct ip *ip;
883 	int len;
884 	int is_idle;
885 
886 	/* change recvif */
887 	m0->m_pkthdr.ph_ifidx = session->ifindex;
888 
889 	if (ISSET(session->ppp_flags, PIPEX_PPP_INGRESS_FILTER)) {
890 		PIPEX_PULLUP(m0, sizeof(struct ip));
891 		if (m0 == NULL)
892 			goto drop;
893 		/* ingress filter */
894 		ip = mtod(m0, struct ip *);
895 		if ((ip->ip_src.s_addr & session->ip_netmask.sin_addr.s_addr) !=
896 		    session->ip_address.sin_addr.s_addr) {
897 			char src[INET_ADDRSTRLEN];
898 
899 			pipex_session_log(session, LOG_DEBUG,
900 			    "ip packet discarded by ingress filter (src %s)",
901 			    inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)));
902 			goto drop;
903 		}
904 	}
905 
906 	/* idle timer */
907 	if (session->timeout_sec != 0) {
908 		is_idle = 0;
909 		m0 = ip_is_idle_packet(m0, &is_idle);
910 		if (m0 == NULL)
911 			goto drop;
912 		if (is_idle == 0)
913 			/* update expire time */
914 			session->idle_time = 0;
915 	}
916 
917 	/* adjust tcpmss */
918 	if (session->ppp_flags & PIPEX_PPP_ADJUST_TCPMSS) {
919 		m0 = adjust_tcp_mss(m0, session->peer_mru);
920 		if (m0 == NULL)
921 			goto drop;
922 	}
923 
924 #if NPF > 0
925 	pf_pkt_addr_changed(m0);
926 #endif
927 
928 	len = m0->m_pkthdr.len;
929 
930 	if ((ifp = if_get(session->ifindex)) == NULL)
931 		goto drop;
932 
933 #if NBPFILTER > 0
934 	if (ifp->if_bpf)
935 		bpf_mtap_af(ifp->if_bpf, AF_INET, m0, BPF_DIRECTION_IN);
936 #endif
937 
938 	counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, len);
939 	counters_pkt(session->stat_counters, pxc_ipackets, pxc_ibytes, len);
940 	ipv4_input(ifp, m0);
941 
942 	if_put(ifp);
943 
944 	return;
945 drop:
946 	m_freem(m0);
947 	counters_inc(session->stat_counters, pxc_ierrors);
948 }
949 
950 #ifdef INET6
951 Static void
952 pipex_ip6_input(struct mbuf *m0, struct pipex_session *session)
953 {
954 	struct ifnet *ifp;
955 	int len;
956 
957 	/* change recvif */
958 	m0->m_pkthdr.ph_ifidx = session->ifindex;
959 
960 	/*
961 	 * XXX: what is reasonable ingress filter ???
962 	 *      only one address is enough ??
963 	 */
964 
965 	/* XXX: we must define idle packet for IPv6(ICMPv6). */
966 
967 	/*
968 	 * XXX: tcpmss adjustment for IPv6 is required???
969 	 *      We may use PMTUD in IPv6....
970 	 */
971 
972 #if NPF > 0
973 	pf_pkt_addr_changed(m0);
974 #endif
975 
976 	len = m0->m_pkthdr.len;
977 
978 	if ((ifp = if_get(session->ifindex)) == NULL)
979 		goto drop;
980 
981 #if NBPFILTER > 0
982 	if (ifp->if_bpf)
983 		bpf_mtap_af(ifp->if_bpf, AF_INET6, m0, BPF_DIRECTION_IN);
984 #endif
985 
986 	counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, len);
987 	counters_pkt(session->stat_counters, pxc_ipackets, pxc_ibytes, len);
988 	ipv6_input(ifp, m0);
989 
990 	if_put(ifp);
991 
992 	return;
993 drop:
994 	m_freem(m0);
995 	counters_inc(session->stat_counters, pxc_ierrors);
996 }
997 #endif
998 
999 Static struct mbuf *
1000 pipex_common_input(struct pipex_session *session, struct mbuf *m0, int hlen,
1001     int plen)
1002 {
1003 	int proto, ppphlen;
1004 	u_char code;
1005 
1006 	if ((m0->m_pkthdr.len < hlen + PIPEX_PPPMINLEN) ||
1007 	    (plen < PIPEX_PPPMINLEN))
1008 		goto drop;
1009 
1010 	proto = pipex_ppp_proto(m0, session, hlen, &ppphlen);
1011 	switch (proto) {
1012 #ifdef PIPEX_MPPE
1013 	case PPP_CCP:
1014 		code = 0;
1015 		KASSERT(m0->m_pkthdr.len >= hlen + ppphlen + 1);
1016 		m_copydata(m0, hlen + ppphlen, 1, &code);
1017 		if (code != CCP_RESETREQ && code != CCP_RESETACK)
1018 			goto not_ours;
1019 		break;
1020 
1021 	case PPP_COMP:
1022 		if (pipex_session_is_mppe_accepted(session))
1023 			break;
1024 		goto not_ours;
1025 #endif
1026 	case PPP_IP:
1027 #ifdef INET6
1028 	case PPP_IPV6:
1029 #endif
1030 		break;
1031 	default:
1032 		goto not_ours;
1033 	}
1034 
1035 	/* ok,  The packet is for PIPEX */
1036 	m_adj(m0, hlen);/* cut off the tunnle protocol header */
1037 
1038 	/* ensure the mbuf length equals the PPP frame length */
1039 	if (m0->m_pkthdr.len < plen)
1040 		goto drop;
1041 	if (m0->m_pkthdr.len > plen) {
1042 		if (m0->m_len == m0->m_pkthdr.len) {
1043 			m0->m_len = plen;
1044 			m0->m_pkthdr.len = plen;
1045 		} else
1046 			m_adj(m0, plen - m0->m_pkthdr.len);
1047 	}
1048 
1049 	pipex_ppp_input(m0, session, 0);
1050 
1051 	return (NULL);
1052 
1053 drop:
1054 	m_freem(m0);
1055 	counters_inc(session->stat_counters, pxc_ierrors);
1056 	return (NULL);
1057 
1058 not_ours:
1059 	return (m0);	/* Not to be handled by PIPEX */
1060 }
1061 
1062 /*
1063  * pipex_ppp_proto
1064  */
1065 Static int
1066 pipex_ppp_proto(struct mbuf *m0, struct pipex_session *session, int off,
1067     int *hlenp)
1068 {
1069 	int proto;
1070 	u_char *cp, pktbuf[4];
1071 
1072 	KASSERT(m0->m_pkthdr.len > sizeof(pktbuf));
1073 	m_copydata(m0, off, sizeof(pktbuf), pktbuf);
1074 	cp = pktbuf;
1075 
1076 	if (pipex_session_has_acf(session)) {
1077 		if (cp[0] == PPP_ALLSTATIONS && cp[1] == PPP_UI)
1078 			cp += 2;
1079 #ifdef PIPEX_DEBUG
1080 		else if (!pipex_session_is_acfc_accepted(session))
1081 			PIPEX_DBG((session, LOG_DEBUG,
1082 			    "no acf but acfc is not accepted by the peer."));
1083 #endif
1084 	}
1085 	if ((*cp & 0x01) != 0) {
1086 		if (!pipex_session_is_pfc_accepted(session)) {
1087 			PIPEX_DBG((session, LOG_DEBUG, "Received a broken ppp "
1088 			    "frame.  No protocol field. %02x-%02x",
1089 			    cp[0], cp[1]));
1090 			return (-1);
1091 		}
1092 		GETCHAR(proto, cp);
1093 	} else
1094 		GETSHORT(proto, cp);
1095 
1096 	if (hlenp != NULL)
1097 		*hlenp = cp - pktbuf;
1098 
1099 	return (proto);
1100 }
1101 
1102 #ifdef PIPEX_PPPOE
1103 /***********************************************************************
1104  * PPPoE
1105  ***********************************************************************/
1106 Static u_char	pipex_pppoe_padding[ETHERMIN];
1107 /*
1108  * pipex_pppoe_lookup_session
1109  */
1110 struct pipex_session *
1111 pipex_pppoe_lookup_session(struct mbuf *m0)
1112 {
1113 	struct pipex_session *session;
1114 	struct pipex_pppoe_header pppoe;
1115 
1116 	/* short packet */
1117 	if (m0->m_pkthdr.len < (sizeof(struct ether_header) + sizeof(pppoe)))
1118 		return (NULL);
1119 
1120 	m_copydata(m0, sizeof(struct ether_header),
1121 	    sizeof(struct pipex_pppoe_header), &pppoe);
1122 	pppoe.session_id = ntohs(pppoe.session_id);
1123 	session = pipex_lookup_by_session_id(PIPEX_PROTO_PPPOE,
1124 	    pppoe.session_id);
1125 #ifdef PIPEX_DEBUG
1126 	if (session == NULL)
1127 		PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (id=%d)",
1128 		    __func__, pppoe.session_id));
1129 #endif
1130 	if (session && session->proto.pppoe.over_ifidx != m0->m_pkthdr.ph_ifidx)
1131 		session = NULL;
1132 
1133 	return (session);
1134 }
1135 
1136 struct mbuf *
1137 pipex_pppoe_input(struct mbuf *m0, struct pipex_session *session)
1138 {
1139 	int hlen;
1140 	struct pipex_pppoe_header pppoe;
1141 
1142 	NET_ASSERT_LOCKED();
1143 	/* already checked at pipex_pppoe_lookup_session */
1144 	KASSERT(m0->m_pkthdr.len >= (sizeof(struct ether_header) +
1145 	    sizeof(pppoe)));
1146 
1147 	m_copydata(m0, sizeof(struct ether_header),
1148 	    sizeof(struct pipex_pppoe_header), &pppoe);
1149 
1150 	hlen = sizeof(struct ether_header) + sizeof(struct pipex_pppoe_header);
1151 	if ((m0 = pipex_common_input(session, m0, hlen, ntohs(pppoe.length)))
1152 	    == NULL)
1153 		return (NULL);
1154 	m_freem(m0);
1155 	counters_inc(session->stat_counters, pxc_ierrors);
1156 	return (NULL);
1157 }
1158 
1159 /*
1160  * pipex_ppope_output
1161  */
1162 Static void
1163 pipex_pppoe_output(struct mbuf *m0, struct pipex_session *session)
1164 {
1165 	struct pipex_pppoe_header *pppoe;
1166 	struct ifnet *ifp;
1167 	int len, padlen;
1168 
1169 	/* save length for pppoe header */
1170 	len = m0->m_pkthdr.len;
1171 
1172 	/* prepend protocol header */
1173 	M_PREPEND(m0, sizeof(struct pipex_pppoe_header), M_NOWAIT);
1174 	if (m0 == NULL) {
1175 		PIPEX_DBG((NULL, LOG_ERR,
1176 		    "<%s> cannot prepend header.", __func__));
1177 		counters_inc(session->stat_counters, pxc_oerrors);
1178 		return;
1179 	}
1180 	padlen = ETHERMIN - m0->m_pkthdr.len;
1181 	if (padlen > 0)
1182 		m_copyback(m0, m0->m_pkthdr.len, padlen, pipex_pppoe_padding,
1183 		    M_NOWAIT);
1184 
1185 	/* setup pppoe header information */
1186 	pppoe = mtod(m0, struct pipex_pppoe_header *);
1187 	pppoe->vertype = PIPEX_PPPOE_VERTYPE;
1188 	pppoe->code = PIPEX_PPPOE_CODE_SESSION;
1189 	pppoe->session_id = htons(session->session_id);
1190 	pppoe->length = htons(len);
1191 
1192 	m0->m_pkthdr.ph_ifidx = session->proto.pppoe.over_ifidx;
1193 	m0->m_flags &= ~(M_BCAST|M_MCAST);
1194 
1195 	ifp = if_get(session->proto.pppoe.over_ifidx);
1196 	if (ifp != NULL) {
1197 		ifp->if_output(ifp, m0, &session->peer.sa, NULL);
1198 		counters_pkt(session->stat_counters, pxc_opackets,
1199 		    pxc_obytes, len);
1200 	} else {
1201 		m_freem(m0);
1202 		counters_inc(session->stat_counters, pxc_oerrors);
1203 	}
1204 	if_put(ifp);
1205 }
1206 #endif /* PIPEX_PPPOE */
1207 
1208 #ifdef PIPEX_PPTP
1209 /***********************************************************************
1210  * PPTP
1211  ***********************************************************************/
1212 Static void
1213 pipex_pptp_output(struct mbuf *m0, struct pipex_session *session,
1214     int has_seq, int has_ack)
1215 {
1216 	int len, reqlen;
1217 	struct pipex_gre_header *gre = NULL;
1218 	struct ip *ip;
1219 	u_char *cp;
1220 
1221 	reqlen = PIPEX_IPGRE_HDRLEN + (has_seq + has_ack) * 4;
1222 
1223 	len = 0;
1224 	if (m0 != NULL) {
1225 		/* save length for gre header */
1226 		len = m0->m_pkthdr.len;
1227 		/* prepend protocol header */
1228 		M_PREPEND(m0, reqlen, M_NOWAIT);
1229 		if (m0 == NULL)
1230 			goto drop;
1231 	} else {
1232 		MGETHDR(m0, M_DONTWAIT, MT_DATA);
1233 		if (m0 && reqlen > MHLEN) {
1234 			MCLGET(m0, M_DONTWAIT);
1235 			if ((m0->m_flags & M_EXT) == 0) {
1236 				m_freem(m0);
1237 				m0 = NULL;
1238 			}
1239 		}
1240 		if (m0 == NULL)
1241 			goto drop;
1242 		m0->m_pkthdr.len = m0->m_len = reqlen;
1243 	}
1244 
1245 	/* setup ip header information */
1246 	ip = mtod(m0, struct ip *);
1247 
1248 	ip->ip_len = htons(m0->m_pkthdr.len);
1249 	ip->ip_off = 0;
1250 	ip->ip_ttl = MAXTTL;
1251 	ip->ip_p = IPPROTO_GRE;
1252 	ip->ip_tos = 0;
1253 
1254 	ip->ip_src = session->local.sin4.sin_addr;
1255 	ip->ip_dst = session->peer.sin4.sin_addr;
1256 #if NPF > 0
1257 	pf_pkt_addr_changed(m0);
1258 #endif
1259 
1260 	/* setup gre(ver1) header information */
1261 	gre = PIPEX_SEEK_NEXTHDR(ip, sizeof(struct ip),
1262 	    struct pipex_gre_header *);
1263 	gre->type = htons(PIPEX_GRE_PROTO_PPP);
1264 	gre->call_id = htons(session->peer_session_id);
1265 	gre->flags = PIPEX_GRE_KFLAG | PIPEX_GRE_VER;	/* do htons later */
1266 	gre->len = htons(len);
1267 
1268 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
1269 	if (has_seq) {
1270 		gre->flags |= PIPEX_GRE_SFLAG;
1271 		PUTLONG(session->proto.pptp.snd_nxt, cp);
1272 		session->proto.pptp.snd_nxt++;
1273 		session->proto.pptp.snd_gap++;
1274 	}
1275 	if (has_ack) {
1276 		gre->flags |= PIPEX_GRE_AFLAG;
1277 		session->proto.pptp.rcv_acked = session->proto.pptp.rcv_nxt - 1;
1278 		PUTLONG(session->proto.pptp.rcv_acked, cp);
1279 	}
1280 	gre->flags = htons(gre->flags);
1281 
1282 	m0->m_pkthdr.ph_ifidx = session->ifindex;
1283 	ip_send(m0);
1284 	if (len > 0) {	/* network layer only */
1285 		/* countup statistics */
1286 		counters_pkt(session->stat_counters, pxc_opackets,
1287 		    pxc_obytes, len);
1288 	}
1289 
1290 	return;
1291 drop:
1292 	counters_inc(session->stat_counters, pxc_oerrors);
1293 }
1294 
1295 struct pipex_session *
1296 pipex_pptp_lookup_session(struct mbuf *m0)
1297 {
1298 	struct pipex_session *session;
1299 	struct pipex_gre_header gre;
1300 	struct ip ip;
1301 	uint16_t flags;
1302 	uint16_t id;
1303 	int hlen;
1304 
1305 	if (m0->m_pkthdr.len < PIPEX_IPGRE_HDRLEN) {
1306 		PIPEX_DBG((NULL, LOG_DEBUG,
1307 		    "<%s> packet length is too short", __func__));
1308 		goto not_ours;
1309 	}
1310 
1311 	/* get ip header info */
1312 	m_copydata(m0, 0, sizeof(struct ip), &ip);
1313 	hlen = ip.ip_hl << 2;
1314 
1315 	/*
1316 	 * m0 has already passed ip_input(), so there is
1317 	 * no necessity for ip packet inspection.
1318 	 */
1319 
1320 	/* get gre flags */
1321 	m_copydata(m0, hlen, sizeof(gre), &gre);
1322 	flags = ntohs(gre.flags);
1323 
1324 	/* gre version must be '1' */
1325 	if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
1326 		PIPEX_DBG((NULL, LOG_DEBUG,
1327 		    "<%s> gre header wrong version.", __func__));
1328 		goto not_ours;
1329 	}
1330 
1331 	/* gre keys must be present */
1332 	if ((flags & PIPEX_GRE_KFLAG) == 0) {
1333 		PIPEX_DBG((NULL, LOG_DEBUG,
1334 		    "<%s> gre header has no keys.", __func__));
1335 		goto not_ours;
1336 	}
1337 
1338 	/* flag check */
1339 	if ((flags & PIPEX_GRE_UNUSEDFLAGS) != 0) {
1340 		PIPEX_DBG((NULL, LOG_DEBUG,
1341 		    "<%s> gre header has unused flags at pptp.", __func__));
1342 		goto not_ours;
1343 	}
1344 
1345 	/* lookup pipex session table */
1346 	id = ntohs(gre.call_id);
1347 	session = pipex_lookup_by_session_id(PIPEX_PROTO_PPTP, id);
1348 #ifdef PIPEX_DEBUG
1349 	if (session == NULL) {
1350 		PIPEX_DBG((NULL, LOG_DEBUG,
1351 		    "<%s> session not found (id=%d)", __func__, id));
1352 		goto not_ours;
1353 	}
1354 #endif
1355 
1356 	return (session);
1357 
1358 not_ours:
1359 	return (NULL);
1360 }
1361 
1362 struct mbuf *
1363 pipex_pptp_input(struct mbuf *m0, struct pipex_session *session)
1364 {
1365 	int hlen, has_seq, has_ack, nseq;
1366 	const char *reason = "";
1367 	u_char *cp, *seqp = NULL, *ackp = NULL;
1368 	uint32_t flags, seq = 0, ack = 0;
1369 	struct ip *ip;
1370 	struct pipex_gre_header *gre;
1371 	struct pipex_pptp_session *pptp_session;
1372 	int rewind = 0;
1373 
1374 	NET_ASSERT_LOCKED();
1375 	KASSERT(m0->m_pkthdr.len >= PIPEX_IPGRE_HDRLEN);
1376 	pptp_session = &session->proto.pptp;
1377 
1378 	/* get ip header */
1379 	ip = mtod(m0, struct ip *);
1380 	hlen = ip->ip_hl << 2;
1381 
1382 	/* seek gre header */
1383 	gre = PIPEX_SEEK_NEXTHDR(ip, hlen, struct pipex_gre_header *);
1384 	flags = ntohs(gre->flags);
1385 
1386 	/* pullup for seek sequences in header */
1387 	has_seq = (flags & PIPEX_GRE_SFLAG) ? 1 : 0;
1388 	has_ack = (flags & PIPEX_GRE_AFLAG) ? 1 : 0;
1389 	hlen = PIPEX_IPGRE_HDRLEN + 4 * (has_seq + has_ack);
1390 	if (m0->m_len < hlen) {
1391 		m0 = m_pullup(m0, hlen);
1392 		if (m0 == NULL) {
1393 			PIPEX_DBG((session, LOG_DEBUG, "pullup failed."));
1394 			goto drop;
1395 		}
1396 	}
1397 
1398 	/* check sequence */
1399 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
1400 	if (has_seq) {
1401 		seqp = cp;
1402 		GETLONG(seq, cp);
1403 	}
1404 	if (has_ack) {
1405 		ackp = cp;
1406 		GETLONG(ack, cp);
1407 		if (ack + 1 == pptp_session->snd_una) {
1408 			/* ack has not changed before */
1409 		} else if (SEQ32_LT(ack, pptp_session->snd_una)) {
1410 			/* OoO ack packets should not be dropped. */
1411 			rewind = 1;
1412 		} else if (SEQ32_GT(ack, pptp_session->snd_nxt)) {
1413 			reason = "ack for unknown sequence";
1414 			goto out_seq;
1415 		} else
1416 			pptp_session->snd_una = ack + 1;
1417 	}
1418 	if (!has_seq) {
1419 		/* ack only packet */
1420 		goto not_ours;
1421 	}
1422 	if (SEQ32_LT(seq, pptp_session->rcv_nxt)) {
1423 		rewind = 1;
1424 		if (SEQ32_LT(seq,
1425 		    pptp_session->rcv_nxt - PIPEX_REWIND_LIMIT)) {
1426 			reason = "out of sequence";
1427 			goto out_seq;
1428 		}
1429 	} else if (SEQ32_GE(seq, pptp_session->rcv_nxt +
1430 	    pptp_session->maxwinsz)) {
1431 		pipex_session_log(session, LOG_DEBUG,
1432 		    "received packet caused window overflow. seq=%u(%u-%u)"
1433 		    "may lost %d packets.", seq, pptp_session->rcv_nxt,
1434 		    pptp_session->rcv_nxt + pptp_session->maxwinsz,
1435 		    (int)SEQ32_SUB(seq, pptp_session->rcv_nxt));
1436 	}
1437 
1438 	seq++;
1439 	nseq = SEQ32_SUB(seq, pptp_session->rcv_nxt);
1440 	if (!rewind) {
1441 		pptp_session->rcv_nxt = seq;
1442 		if (SEQ32_SUB(seq, pptp_session->rcv_acked) >
1443 		    roundup(pptp_session->winsz, 2) / 2) /* Send ack only packet. */
1444 			pipex_pptp_output(NULL, session, 0, 1);
1445 	}
1446 
1447 	if ((m0 = pipex_common_input(session, m0, hlen, ntohs(gre->len)))
1448 	    == NULL) {
1449 		/* ok,  The packet is for PIPEX */
1450 		if (!rewind)
1451 			session->proto.pptp.rcv_gap += nseq;
1452 		return (NULL);
1453 	}
1454 
1455 	if (rewind)
1456 		goto out_seq;
1457 
1458 not_ours:
1459 	seq--;	/* revert original seq value */
1460 
1461 	/*
1462 	 * overwrite sequence numbers to adjust a gap between pipex and
1463 	 * userland.
1464 	 */
1465 	if (seqp != NULL) {
1466 		seq -= pptp_session->rcv_gap;
1467 		PUTLONG(seq, seqp);
1468 	}
1469 	if (ackp != NULL) {
1470 		if (pptp_session->snd_nxt == pptp_session->snd_una) {
1471 			ack -= session->proto.pptp.snd_gap;
1472 			pptp_session->ul_snd_una = ack;
1473 		} else {
1474 			/*
1475 			 * There are sending packets they are not acked.
1476 			 * In this situation, (ack - snd_gap) may points
1477 			 * before sending window of userland.  So we don't
1478 			 * update the ack number.
1479 			 */
1480 			ack = pptp_session->ul_snd_una;
1481 		}
1482 		PUTLONG(ack, ackp);
1483 	}
1484 
1485 	return (m0);
1486 out_seq:
1487 	pipex_session_log(session, LOG_DEBUG,
1488 	    "Received bad data packet: %s: seq=%u(%u-%u) ack=%u(%u-%u)",
1489 	    reason, seq, pptp_session->rcv_nxt,
1490 	    pptp_session->rcv_nxt + pptp_session->maxwinsz,
1491 	    ack, pptp_session->snd_una,
1492 	    pptp_session->snd_nxt);
1493 
1494 	/* FALLTHROUGH */
1495 drop:
1496 	m_freem(m0);
1497 	counters_inc(session->stat_counters, pxc_ierrors);
1498 
1499 	return (NULL);
1500 }
1501 
1502 struct pipex_session *
1503 pipex_pptp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
1504 {
1505 	struct sockaddr_in sin;
1506 
1507 	memset(&sin, 0, sizeof(sin));
1508 	sin.sin_len = sizeof(sin);
1509 	sin.sin_family = AF_INET;
1510 	sin.sin_addr = dst;
1511 
1512 	return pipex_pptp_userland_lookup_session(m0, sintosa(&sin));
1513 }
1514 
1515 #ifdef INET6
1516 struct pipex_session *
1517 pipex_pptp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
1518 {
1519 	struct sockaddr_in6 sin6;
1520 
1521 	memset(&sin6, 0, sizeof(sin6));
1522 	sin6.sin6_len = sizeof(sin6);
1523 	sin6.sin6_family = AF_INET6;
1524 	in6_recoverscope(&sin6, &dst);
1525 
1526 	return pipex_pptp_userland_lookup_session(m0, sin6tosa(&sin6));
1527 }
1528 #endif
1529 
1530 Static struct pipex_session *
1531 pipex_pptp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
1532 {
1533 	struct pipex_gre_header gre;
1534 	struct pipex_hash_head *list;
1535 	struct pipex_session *session;
1536 	uint16_t id, flags;
1537 
1538 	/* pullup */
1539 	if (m0->m_pkthdr.len < sizeof(gre)) {
1540 		PIPEX_DBG((NULL, LOG_DEBUG,
1541 		    "<%s> packet length is too short", __func__));
1542 		return (NULL);
1543 	}
1544 
1545 	/* get flags */
1546 	m_copydata(m0, 0, sizeof(struct pipex_gre_header), &gre);
1547 	flags = ntohs(gre.flags);
1548 
1549 	/* gre version must be '1' */
1550 	if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
1551 		PIPEX_DBG((NULL, LOG_DEBUG,
1552 		    "<%s> gre header wrong version.", __func__));
1553 		return (NULL);
1554 	}
1555 
1556 	/* gre keys must be present */
1557 	if ((flags & PIPEX_GRE_KFLAG) == 0) {
1558 		PIPEX_DBG((NULL, LOG_DEBUG,
1559 		    "<%s> gre header has no keys.", __func__));
1560 		return (NULL);
1561 	}
1562 
1563 	/* lookup pipex session table */
1564 	id = ntohs(gre.call_id);
1565 
1566 	list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
1567 	LIST_FOREACH(session, list, peer_addr_chain) {
1568 		if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
1569 			continue;
1570 		if (session->peer_session_id == id)
1571 			break;
1572 	}
1573 #ifdef PIPEX_DEBUG
1574 	if (session == NULL) {
1575 		PIPEX_DBG((NULL, LOG_DEBUG,
1576 		    "<%s> session not found (,call_id=%d)",
1577 		    __func__, (int)gre.call_id));
1578 	}
1579 #endif
1580 	return (session);
1581 }
1582 
1583 /*
1584  * pipex_pptp_userland_output
1585  */
1586 struct mbuf *
1587 pipex_pptp_userland_output(struct mbuf *m0, struct pipex_session *session)
1588 {
1589 	int len;
1590 	struct pipex_gre_header *gre, gre0;
1591 	uint16_t flags;
1592 	u_char *cp, *cp0;
1593 	uint32_t val32;
1594 
1595 	len = sizeof(struct pipex_gre_header);
1596 	m_copydata(m0, 0, len, &gre0);
1597 	gre = &gre0;
1598 	flags = ntohs(gre->flags);
1599 	if ((flags & PIPEX_GRE_SFLAG) != 0)
1600 		len += 4;
1601 	if ((flags & PIPEX_GRE_AFLAG) != 0)
1602 		len += 4;
1603 
1604 	/* check length */
1605 	PIPEX_PULLUP(m0, len);
1606 	if (m0 == NULL) {
1607 		PIPEX_DBG((session, LOG_DEBUG, "gre header is too short."));
1608 		return (NULL);
1609 	}
1610 
1611 	gre = mtod(m0, struct pipex_gre_header *);
1612 	cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header), u_char *);
1613 
1614 	/*
1615 	 * overwrite sequence numbers to adjust a gap between pipex and
1616 	 * userland.
1617 	 */
1618 	if ((flags & PIPEX_GRE_SFLAG) != 0) {
1619 		cp0 = cp;
1620 		GETLONG(val32, cp);
1621 		val32 += session->proto.pptp.snd_gap;
1622 		PUTLONG(val32, cp0);
1623 		session->proto.pptp.snd_nxt++;
1624 	}
1625 	if ((flags & PIPEX_GRE_AFLAG) != 0) {
1626 		cp0 = cp;
1627 		GETLONG(val32, cp);
1628 		val32 += session->proto.pptp.rcv_gap;
1629 		PUTLONG(val32, cp0);
1630 		if (SEQ32_GT(val32, session->proto.pptp.rcv_acked))
1631 			session->proto.pptp.rcv_acked = val32;
1632 	}
1633 
1634 	return (m0);
1635 }
1636 #endif /* PIPEX_PPTP */
1637 
1638 #ifdef PIPEX_L2TP
1639 /***********************************************************************
1640  * L2TP support
1641  ***********************************************************************/
1642 Static void
1643 pipex_l2tp_output(struct mbuf *m0, struct pipex_session *session)
1644 {
1645 	int hlen, plen, datalen;
1646 	struct pipex_l2tp_header *l2tp = NULL;
1647 	struct pipex_l2tp_seq_header *seq = NULL;
1648 	struct udphdr *udp;
1649 	struct ip *ip;
1650 #ifdef INET6
1651 	struct ip6_hdr *ip6;
1652 #endif
1653 	struct m_tag *mtag;
1654 
1655 	hlen = sizeof(struct pipex_l2tp_header) +
1656 	    ((pipex_session_is_l2tp_data_sequencing_on(session))
1657 		    ? sizeof(struct pipex_l2tp_seq_header) : 0) +
1658 	    sizeof(struct udphdr) +
1659 #ifdef INET6
1660 	    ((session->peer.sin6.sin6_family == AF_INET6)
1661 		    ? sizeof(struct ip6_hdr) : sizeof(struct ip));
1662 #else
1663 	    sizeof(struct ip);
1664 #endif
1665 
1666 	datalen = 0;
1667 	if (m0 != NULL) {
1668 		datalen = m0->m_pkthdr.len;
1669 		M_PREPEND(m0, hlen, M_NOWAIT);
1670 		if (m0 == NULL)
1671 			goto drop;
1672 	} else {
1673 		MGETHDR(m0, M_DONTWAIT, MT_DATA);
1674 		if (m0 == NULL)
1675 			goto drop;
1676 		KASSERT(hlen <= MHLEN);
1677 		m0->m_pkthdr.len = m0->m_len = hlen;
1678 	}
1679 
1680 #ifdef INET6
1681 	hlen = (session->peer.sin6.sin6_family == AF_INET6)
1682 	    ? sizeof(struct ip6_hdr) : sizeof(struct ip);
1683 #else
1684 	hlen = sizeof(struct ip);
1685 #endif
1686 	plen = datalen + sizeof(struct pipex_l2tp_header) +
1687 	    ((pipex_session_is_l2tp_data_sequencing_on(session))
1688 		    ? sizeof(struct pipex_l2tp_seq_header) : 0);
1689 
1690 	l2tp = (struct pipex_l2tp_header *)
1691 	    (mtod(m0, caddr_t) + hlen + sizeof(struct udphdr));
1692 	l2tp->flagsver = PIPEX_L2TP_VER | PIPEX_L2TP_FLAG_LENGTH;
1693 	l2tp->length = htons(plen);
1694 	l2tp->tunnel_id = htons(session->proto.l2tp.peer_tunnel_id);
1695 	l2tp->session_id = htons(session->peer_session_id);
1696 	if (pipex_session_is_l2tp_data_sequencing_on(session)) {
1697 		seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
1698 		l2tp->flagsver |= PIPEX_L2TP_FLAG_SEQUENCE;
1699 		seq->ns = htons(session->proto.l2tp.ns_nxt);
1700 		session->proto.l2tp.ns_nxt++;
1701 		session->proto.l2tp.ns_gap++;
1702 		session->proto.l2tp.nr_acked = session->proto.l2tp.nr_nxt - 1;
1703 		seq->nr = htons(session->proto.l2tp.nr_acked);
1704 	}
1705 	l2tp->flagsver = htons(l2tp->flagsver);
1706 
1707 	plen += sizeof(struct udphdr);
1708 	udp = (struct udphdr *)(mtod(m0, caddr_t) + hlen);
1709 	udp->uh_sport = session->local.sin6.sin6_port;
1710 	udp->uh_dport = session->peer.sin6.sin6_port;
1711 	udp->uh_ulen = htons(plen);
1712 	udp->uh_sum = 0;
1713 
1714 	m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
1715 	m0->m_pkthdr.ph_ifidx = session->ifindex;
1716 #if NPF > 0
1717 	pf_pkt_addr_changed(m0);
1718 #endif
1719 	switch (session->peer.sin6.sin6_family) {
1720 	case AF_INET:
1721 		ip = mtod(m0, struct ip *);
1722 		ip->ip_p = IPPROTO_UDP;
1723 		ip->ip_src = session->local.sin4.sin_addr;
1724 		ip->ip_dst = session->peer.sin4.sin_addr;
1725 		ip->ip_len = htons(hlen + plen);
1726 		ip->ip_ttl = MAXTTL;
1727 		ip->ip_tos = 0;
1728 		ip->ip_off = 0;
1729 
1730 		if (session->proto.l2tp.ipsecflowinfo > 0) {
1731 			if ((mtag = m_tag_get(PACKET_TAG_IPSEC_FLOWINFO,
1732 			    sizeof(u_int32_t), M_NOWAIT)) == NULL)
1733 				goto drop;
1734 			*(u_int32_t *)(mtag + 1) =
1735 			    session->proto.l2tp.ipsecflowinfo;
1736 			m_tag_prepend(m0, mtag);
1737 		}
1738 
1739 		ip_send(m0);
1740 		break;
1741 #ifdef INET6
1742 	case AF_INET6:
1743 		ip6 = mtod(m0, struct ip6_hdr *);
1744 
1745 		ip6->ip6_flow = 0;
1746 		ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1747 		ip6->ip6_vfc |= IPV6_VERSION;
1748 		ip6->ip6_nxt = IPPROTO_UDP;
1749 		ip6->ip6_src = session->local.sin6.sin6_addr;
1750 		(void)in6_embedscope(&ip6->ip6_dst,
1751 		    &session->peer.sin6, NULL);
1752 		/* ip6->ip6_plen will be filled in ip6_output. */
1753 
1754 		ip6_send(m0);
1755 		break;
1756 #endif
1757 	}
1758 	udpstat_inc(udps_opackets);
1759 
1760 	if (datalen > 0) {	/* network layer only */
1761 		/* countup statistics */
1762 		counters_pkt(session->stat_counters, pxc_opackets,
1763 		    pxc_obytes, datalen);
1764 	}
1765 
1766 	return;
1767 drop:
1768 	m_freem(m0);
1769 	counters_inc(session->stat_counters, pxc_oerrors);
1770 }
1771 
1772 struct pipex_session *
1773 pipex_l2tp_lookup_session(struct mbuf *m0, int off)
1774 {
1775 	struct pipex_session *session;
1776 	uint16_t flags, session_id, ver;
1777 	u_char *cp, buf[PIPEX_L2TP_MINLEN];
1778 
1779 	if (m0->m_pkthdr.len < off + PIPEX_L2TP_MINLEN) {
1780 		PIPEX_DBG((NULL, LOG_DEBUG,
1781 		    "<%s> packet length is too short", __func__));
1782 		goto not_ours;
1783 	}
1784 
1785 	/* get first 16bits of L2TP */
1786 	m_copydata(m0, off, sizeof(buf), buf);
1787 	cp = buf;
1788 	GETSHORT(flags, cp);
1789 	ver = flags & PIPEX_L2TP_VER_MASK;
1790 
1791 	/* l2tp version must be '2' */
1792 	if (ver != PIPEX_L2TP_VER) {
1793 		PIPEX_DBG((NULL, LOG_DEBUG,
1794 		    "<%s> l2tp header wrong version %u.", __func__, ver));
1795 		goto not_ours;
1796 	}
1797 	if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
1798 		goto not_ours;
1799 
1800 	if (flags & PIPEX_L2TP_FLAG_LENGTH)
1801 		cp += 2;			/* skip length field */
1802 	cp += 2;				/* skip tunnel-id field */
1803 	GETSHORT(session_id, cp);		/* get session-id field */
1804 
1805 	/* lookup pipex session table */
1806 	session = pipex_lookup_by_session_id(PIPEX_PROTO_L2TP, session_id);
1807 #ifdef PIPEX_DEBUG
1808 	if (session == NULL) {
1809 		PIPEX_DBG((NULL, LOG_DEBUG,
1810 		    "<%s> session not found (id=%d)", __func__, session_id));
1811 		goto not_ours;
1812 	}
1813 #endif
1814 
1815 	return (session);
1816 
1817 not_ours:
1818 	return (NULL);
1819 }
1820 
1821 struct mbuf *
1822 pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session,
1823     uint32_t ipsecflowinfo)
1824 {
1825 	struct pipex_l2tp_session *l2tp_session;
1826 	int length, offset, hlen, nseq;
1827 	u_char *cp, *nsp, *nrp;
1828 	uint16_t flags, ns = 0, nr = 0;
1829 	int rewind = 0;
1830 
1831 	NET_ASSERT_LOCKED();
1832 	length = offset = ns = nr = 0;
1833 	l2tp_session = &session->proto.l2tp;
1834 	l2tp_session->ipsecflowinfo = ipsecflowinfo;
1835 	nsp = nrp = NULL;
1836 
1837 	m_copydata(m0, off0, sizeof(flags), &flags);
1838 
1839 	flags = ntohs(flags) & PIPEX_L2TP_FLAG_MASK;
1840 	KASSERT((flags & PIPEX_L2TP_FLAG_TYPE) == 0);
1841 
1842 	hlen = 2;				/* flags and version fields */
1843 	if (flags & PIPEX_L2TP_FLAG_LENGTH)	/* length */
1844 		hlen += 2;
1845 	hlen += 4;				/* tunnel-id and session-id */
1846 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE)	/* ns and nr */
1847 		hlen += 4;
1848 	if (flags & PIPEX_L2TP_FLAG_OFFSET)	/* offset */
1849 		hlen += 2;
1850 
1851 	PIPEX_PULLUP(m0, off0 + hlen);
1852 	if (m0  == NULL)
1853 		goto drop;
1854 
1855 	cp = mtod(m0, u_char *) + off0;
1856 	cp += 2;	/* flags and version */
1857 	if (flags & PIPEX_L2TP_FLAG_LENGTH)
1858 		GETSHORT(length, cp);
1859 	else
1860 		length = m0->m_pkthdr.len - off0;
1861 	cp += 4;	/* skip tunnel-id and session-id field */
1862 
1863 	/* pullup for seek sequences in header */
1864 	nseq = 0;
1865 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
1866 		nsp = cp;
1867 		GETSHORT(ns, cp);
1868 		nrp = cp;
1869 		GETSHORT(nr, cp);
1870 
1871 		nr++;
1872 		if (SEQ16_GT(nr, l2tp_session->ns_una) &&
1873 		    SEQ16_LE(nr, l2tp_session->ns_nxt))
1874 			/* update 'ns_una' only if the ns is in valid range */
1875 			l2tp_session->ns_una = nr;
1876 		if (SEQ16_LT(ns, l2tp_session->nr_nxt)) {
1877 			rewind = 1;
1878 			if (SEQ16_LT(ns,
1879 			    l2tp_session->nr_nxt - PIPEX_REWIND_LIMIT))
1880 				goto out_seq;
1881 		}
1882 
1883 		ns++;
1884 		nseq = SEQ16_SUB(ns, l2tp_session->nr_nxt);
1885 		if (!rewind)
1886 			l2tp_session->nr_nxt = ns;
1887 	}
1888 	if (flags & PIPEX_L2TP_FLAG_OFFSET)
1889 		GETSHORT(offset, cp);
1890 
1891 	length -= hlen + offset;
1892 	hlen += off0 + offset;
1893 	if ((m0 = pipex_common_input(session, m0, hlen, length)) == NULL) {
1894 		/* ok,  The packet is for PIPEX */
1895 		if (!rewind)
1896 			session->proto.l2tp.nr_gap += nseq;
1897 		return (NULL);
1898 	}
1899 
1900 	if (rewind)
1901 		goto out_seq;
1902 
1903 	/*
1904 	 * overwrite sequence numbers to adjust a gap between pipex and
1905 	 * userland.
1906 	 */
1907 	if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
1908 		--ns; --nr;	/* revert original values */
1909 		ns -= l2tp_session->nr_gap;
1910 		PUTSHORT(ns, nsp);
1911 
1912 		if (l2tp_session->ns_nxt == l2tp_session->ns_una) {
1913 			nr -= l2tp_session->ns_gap;
1914 			l2tp_session->ul_ns_una = nr;
1915 		} else {
1916 			/*
1917 			 * There are sending packets they are not acked.
1918 			 * In this situation, (ack - snd_gap) may points
1919 			 * before sending window of userland.  So we don't
1920 			 * update the ack number.
1921 			 */
1922 			nr = l2tp_session->ul_ns_una;
1923 		}
1924 		PUTSHORT(nr, nrp);
1925 	}
1926 
1927 	return (m0);
1928 out_seq:
1929 	pipex_session_log(session, LOG_DEBUG,
1930 	    "Received bad data packet: out of sequence: seq=%u(%u-) "
1931 	    "ack=%u(%u-%u)", ns, l2tp_session->nr_nxt, nr, l2tp_session->ns_una,
1932 	    l2tp_session->ns_nxt);
1933 
1934 	/* FALLTHROUGH */
1935 drop:
1936 	m_freem(m0);
1937 	counters_inc(session->stat_counters, pxc_ierrors);
1938 
1939 	return (NULL);
1940 }
1941 
1942 struct pipex_session *
1943 pipex_l2tp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
1944 {
1945 	struct sockaddr_in sin;
1946 
1947 	memset(&sin, 0, sizeof(sin));
1948 	sin.sin_len = sizeof(sin);
1949 	sin.sin_family = AF_INET;
1950 	sin.sin_addr = dst;
1951 
1952 	return pipex_l2tp_userland_lookup_session(m0, sintosa(&sin));
1953 }
1954 
1955 #ifdef INET6
1956 struct pipex_session *
1957 pipex_l2tp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
1958 {
1959 	struct sockaddr_in6 sin6;
1960 
1961 	memset(&sin6, 0, sizeof(sin6));
1962 	sin6.sin6_len = sizeof(sin6);
1963 	sin6.sin6_family = AF_INET6;
1964 	in6_recoverscope(&sin6, &dst);
1965 
1966 	return pipex_l2tp_userland_lookup_session(m0, sin6tosa(&sin6));
1967 }
1968 #endif
1969 
1970 struct pipex_session *
1971 pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
1972 {
1973 	struct pipex_l2tp_header l2tp;
1974 	struct pipex_hash_head *list;
1975 	struct pipex_session *session;
1976 	uint16_t session_id, tunnel_id, flags;
1977 
1978 	if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
1979 		return (NULL);
1980 
1981 	/* pullup */
1982 	if (m0->m_pkthdr.len < sizeof(l2tp)) {
1983 		PIPEX_DBG((NULL, LOG_DEBUG,
1984 		    "<%s> packet length is too short", __func__));
1985 		return (NULL);
1986 	}
1987 
1988 	/* get flags */
1989 	m_copydata(m0, 0, sizeof(l2tp), &l2tp);
1990 	flags = ntohs(l2tp.flagsver);
1991 
1992 	/* l2tp version must be '2' */
1993 	if ((flags & PIPEX_L2TP_VER_MASK) != PIPEX_L2TP_VER) {
1994 		PIPEX_DBG((NULL, LOG_DEBUG,
1995 		    "<%s> l2tp header wrong version.", __func__));
1996 		return (NULL);
1997 	}
1998 	/* We need L2TP data messages only */
1999 	if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
2000 		return (NULL);
2001 	/* No need to hook packets that don't have the sequence field */
2002 	if ((flags & PIPEX_L2TP_FLAG_SEQUENCE) == 0)
2003 		return (NULL);
2004 
2005 	session_id = ntohs(l2tp.session_id);
2006 	tunnel_id = ntohs(l2tp.tunnel_id);
2007 
2008 	list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
2009 	LIST_FOREACH(session, list, peer_addr_chain) {
2010 		if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
2011 			continue;
2012 		if (session->proto.l2tp.peer_tunnel_id != tunnel_id)
2013 			continue;
2014 		if (session->peer_session_id == session_id)
2015 			break;
2016 	}
2017 #ifdef PIPEX_DEBUG
2018 	if (session == NULL) {
2019 		PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found "
2020 		    "(tunnel_id=%d, session_id=%d)", __func__,
2021 		    tunnel_id, session_id));
2022 	}
2023 #endif
2024 
2025 	return (session);
2026 }
2027 
2028 struct mbuf *
2029 pipex_l2tp_userland_output(struct mbuf *m0, struct pipex_session *session)
2030 {
2031 	struct pipex_l2tp_header *l2tp;
2032 	struct pipex_l2tp_seq_header *seq;
2033 	uint16_t ns, nr;
2034 
2035 	/* check length */
2036 	PIPEX_PULLUP(m0, sizeof(struct pipex_l2tp_header) +
2037 	    sizeof(struct pipex_l2tp_seq_header));
2038 	if (m0 == NULL)
2039 		return (NULL);
2040 
2041 	l2tp = mtod(m0, struct pipex_l2tp_header *);
2042 	KASSERT(ntohs(l2tp->flagsver) & PIPEX_L2TP_FLAG_SEQUENCE);
2043 
2044 	/*
2045 	 * overwrite sequence numbers to adjust a gap between pipex and
2046 	 * userland.
2047 	 */
2048 		seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
2049 		ns = ntohs(seq->ns);
2050 		nr = ntohs(seq->nr);
2051 
2052 		ns += session->proto.l2tp.ns_gap;
2053 		seq->ns = htons(ns);
2054 		session->proto.l2tp.ns_nxt++;
2055 
2056 		nr += session->proto.l2tp.nr_gap;
2057 		seq->nr = htons(nr);
2058 		if (SEQ16_GT(nr, session->proto.l2tp.nr_acked))
2059 			session->proto.l2tp.nr_acked = nr;
2060 
2061 	return (m0);
2062 }
2063 #endif /* PIPEX_L2TP */
2064 
2065 #ifdef PIPEX_MPPE
2066 /**********************************************************************
2067  * MPPE
2068  ***********************************************************************/
2069 #define	PIPEX_COHERENCY_CNT_MASK		0x0fff
2070 
2071 static inline int
2072 pipex_mppe_setkey(struct pipex_mppe *mppe)
2073 {
2074 	rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen);
2075 
2076 	return (0);
2077 }
2078 
2079 static inline int
2080 pipex_mppe_setoldkey(struct pipex_mppe *mppe, uint16_t coher_cnt)
2081 {
2082 	KASSERT(mppe->old_session_keys != NULL);
2083 
2084 	rc4_keysetup(&mppe->rc4ctx,
2085 	    mppe->old_session_keys[coher_cnt & PIPEX_MPPE_OLDKEYMASK],
2086 	    mppe->keylen);
2087 
2088 	return (0);
2089 }
2090 
2091 static inline void
2092 pipex_mppe_crypt(struct pipex_mppe *mppe, int len, u_char *indata,
2093     u_char *outdata)
2094 {
2095 	rc4_crypt(&mppe->rc4ctx, indata, outdata, len);
2096 }
2097 
2098 Static void
2099 pipex_mppe_init(struct pipex_mppe *mppe, int stateless, int keylenbits,
2100     u_char *master_key, int has_oldkey)
2101 {
2102 	memset(mppe, 0, sizeof(struct pipex_mppe));
2103 	mtx_init(&mppe->pxm_mtx, IPL_SOFTNET);
2104 	if (stateless)
2105 		mppe->stateless = 1;
2106 	if (has_oldkey)
2107 		mppe->old_session_keys =
2108 		    pool_get(&mppe_key_pool, PR_WAITOK);
2109 	else
2110 		mppe->old_session_keys = NULL;
2111 	memcpy(mppe->master_key, master_key, sizeof(mppe->master_key));
2112 
2113 	mppe->keylenbits = keylenbits;
2114 	switch (keylenbits) {
2115 	case 40:
2116 	case 56:
2117 		mppe->keylen = 8;
2118 		break;
2119 	case 128:
2120 		mppe->keylen = 16;
2121 		break;
2122 	}
2123 
2124 	GetNewKeyFromSHA(mppe->master_key, mppe->master_key, mppe->keylen,
2125 	    mppe->session_key);
2126 	pipex_mppe_reduce_key(mppe);
2127 	pipex_mppe_setkey(mppe);
2128 }
2129 
2130 void
2131 pipex_session_init_mppe_recv(struct pipex_session *session, int stateless,
2132     int keylenbits, u_char *master_key)
2133 {
2134 	pipex_mppe_init(&session->mppe_recv, stateless, keylenbits,
2135 	    master_key, stateless);
2136 	session->ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED;
2137 }
2138 
2139 void
2140 pipex_session_init_mppe_send(struct pipex_session *session, int stateless,
2141     int keylenbits, u_char *master_key)
2142 {
2143 	pipex_mppe_init(&session->mppe_send, stateless, keylenbits,
2144 	    master_key, 0);
2145 	session->ppp_flags |= PIPEX_PPP_MPPE_ENABLED;
2146 }
2147 
2148 #include <crypto/sha1.h>
2149 
2150 static u_char SHAPad1[] = {
2151 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2152 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2153 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2154 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2155 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2156 }, SHAPad2[] = {
2157 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2158 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2159 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2160 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2161 	0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2162 };
2163 
2164 Static void
2165 GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength,
2166     u_char *InterimKey)
2167 {
2168 	u_char Digest[20];
2169 	SHA1_CTX Context;
2170 
2171 	SHA1Init(&Context);
2172 	SHA1Update(&Context, StartKey, SessionKeyLength);
2173 	SHA1Update(&Context, SHAPad1, 40);
2174 	SHA1Update(&Context, SessionKey, SessionKeyLength);
2175 	SHA1Update(&Context, SHAPad2, 40);
2176 	SHA1Final(Digest, &Context);
2177 
2178 	memcpy(InterimKey, Digest, SessionKeyLength);
2179 }
2180 
2181 Static void
2182 pipex_mppe_reduce_key(struct pipex_mppe *mppe)
2183 {
2184 	switch (mppe->keylenbits) {
2185 	case 40:
2186 		mppe->session_key[0] = 0xd1;
2187 		mppe->session_key[1] = 0x26;
2188 		mppe->session_key[2] = 0x9e;
2189 		break;
2190 	case 56:
2191 		mppe->session_key[0] = 0xd1;
2192 		break;
2193 	}
2194 }
2195 
2196 Static void
2197 mppe_key_change(struct pipex_mppe *mppe)
2198 {
2199 	u_char interim[16];
2200 	struct rc4_ctx keychg;
2201 
2202 	memset(&keychg, 0, sizeof(keychg));
2203 
2204 	GetNewKeyFromSHA(mppe->master_key, mppe->session_key, mppe->keylen,
2205 	    interim);
2206 
2207 	rc4_keysetup(&keychg, interim, mppe->keylen);
2208 	rc4_crypt(&keychg, interim, mppe->session_key, mppe->keylen);
2209 
2210 	pipex_mppe_reduce_key(mppe);
2211 
2212 	if (mppe->old_session_keys) {
2213 		int idx = mppe->coher_cnt & PIPEX_MPPE_OLDKEYMASK;
2214 		memcpy(mppe->old_session_keys[idx],
2215 		    mppe->session_key, PIPEX_MPPE_KEYLEN);
2216 	}
2217 }
2218 
2219 Static void
2220 pipex_mppe_input(struct mbuf *m0, struct pipex_session *session)
2221 {
2222 	int pktloss, encrypt, flushed, m, n, len;
2223 	struct pipex_mppe *mppe;
2224 	uint16_t coher_cnt;
2225 	struct mbuf *m1;
2226 	u_char *cp;
2227 	int rewind = 0;
2228 
2229 	/* pullup */
2230 	PIPEX_PULLUP(m0, sizeof(coher_cnt));
2231 	if (m0 == NULL)
2232 		goto drop;
2233 
2234 	mppe = &session->mppe_recv;
2235 	/* get header information */
2236 	cp = mtod(m0, u_char *);
2237 	GETSHORT(coher_cnt, cp);
2238 	flushed = ((coher_cnt & 0x8000) != 0) ? 1 : 0;
2239 	encrypt = ((coher_cnt & 0x1000) != 0) ? 1 : 0;
2240 	coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2241 	pktloss = 0;
2242 
2243 	mtx_enter(&mppe->pxm_mtx);
2244 
2245 	PIPEX_MPPE_DBG((session, LOG_DEBUG, "in coher_cnt=%03x %s%s",
2246 	    mppe->coher_cnt, (flushed) ? "[flushed]" : "",
2247 	    (encrypt) ? "[encrypt]" : ""));
2248 
2249 	if (encrypt == 0) {
2250 		mtx_leave(&mppe->pxm_mtx);
2251 		pipex_session_log(session, LOG_DEBUG,
2252 		    "Received unexpected MPPE packet.(no ecrypt)");
2253 		goto drop;
2254 	}
2255 
2256 	/* adjust mbuf */
2257 	m_adj(m0, sizeof(coher_cnt));
2258 
2259 	/*
2260 	 * L2TP data session may be used without sequencing, PPP frames may
2261 	 * arrive in disorder.  The 'coherency counter' of MPPE detects such
2262 	 * situations, but we cannot distinguish between 'disorder' and
2263 	 * 'packet loss' exactly.
2264 	 *
2265 	 * When 'coherency counter' detects lost packets greater than
2266 	 * (4096 - 256), we treat as 'disorder' otherwise treat as
2267 	 * 'packet loss'.
2268 	 */
2269     {
2270 	int coher_cnt0;
2271 
2272 	coher_cnt0 = coher_cnt;
2273 	if (coher_cnt < mppe->coher_cnt)
2274 		coher_cnt0 += 0x1000;
2275 	if (coher_cnt0 - mppe->coher_cnt > 0x0f00) {
2276 		if (!mppe->stateless ||
2277 		    coher_cnt0 - mppe->coher_cnt
2278 		    <= 0x1000 - PIPEX_MPPE_NOLDKEY) {
2279 			pipex_session_log(session, LOG_DEBUG,
2280 			    "Workaround the out-of-sequence PPP framing problem: "
2281 			    "%d => %d", mppe->coher_cnt, coher_cnt);
2282 			mtx_leave(&mppe->pxm_mtx);
2283 			goto drop;
2284 		}
2285 		rewind = 1;
2286 	}
2287     }
2288 
2289 	if (mppe->stateless != 0) {
2290 		if (!rewind) {
2291 			mppe_key_change(mppe);
2292 			while (mppe->coher_cnt != coher_cnt) {
2293 				mppe->coher_cnt++;
2294 				mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2295 				mppe_key_change(mppe);
2296 				pktloss++;
2297 			}
2298 		}
2299 		pipex_mppe_setoldkey(mppe, coher_cnt);
2300 	} else {
2301 		if (flushed) {
2302 			if (coher_cnt < mppe->coher_cnt) {
2303 				coher_cnt += 0x1000;
2304 			}
2305 			pktloss += coher_cnt - mppe->coher_cnt;
2306 			m = mppe->coher_cnt / 256;
2307 			n = coher_cnt / 256;
2308 			while (m++ < n)
2309 				mppe_key_change(mppe);
2310 
2311 			coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2312 			mppe->coher_cnt = coher_cnt;
2313 		} else if (mppe->coher_cnt != coher_cnt) {
2314 			int ccp_id;
2315 
2316 			mtx_leave(&mppe->pxm_mtx);
2317 
2318 			/* Send CCP ResetReq */
2319 			PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetReq"));
2320 
2321 			mtx_enter(&session->pxs_mtx);
2322 			ccp_id = session->ccp_id;
2323 			session->ccp_id++;
2324 			mtx_leave(&session->pxs_mtx);
2325 
2326 			pipex_ccp_output(session, CCP_RESETREQ, ccp_id);
2327 			goto drop;
2328 		}
2329 		if ((coher_cnt & 0xff) == 0xff) {
2330 			mppe_key_change(mppe);
2331 			flushed = 1;
2332 		}
2333 		if (flushed)
2334 			pipex_mppe_setkey(mppe);
2335 	}
2336 
2337 	if (pktloss > 1000) {
2338 		pipex_session_log(session, LOG_DEBUG,
2339 		    "%d packets loss.", pktloss);
2340 	}
2341 
2342 	/* decrypt ppp payload */
2343 	for (m1 = m0; m1; m1 = m1->m_next) {
2344 		cp = mtod(m1, u_char *);
2345 		len = m1->m_len;
2346 		pipex_mppe_crypt(mppe, len, cp, cp);
2347 	}
2348 
2349 	if (!rewind) {
2350 		/* update coher_cnt */
2351 		mppe->coher_cnt++;
2352 		mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2353 	}
2354 
2355 	mtx_leave(&mppe->pxm_mtx);
2356 
2357 	if (m0->m_pkthdr.len < PIPEX_PPPMINLEN)
2358 		goto drop;
2359 
2360 	pipex_ppp_input(m0, session, 1);
2361 
2362 	return;
2363 drop:
2364 	m_freem(m0);
2365 	counters_inc(session->stat_counters, pxc_ierrors);
2366 }
2367 
2368 Static void
2369 pipex_mppe_output(struct mbuf *m0, struct pipex_session *session,
2370     uint16_t protocol)
2371 {
2372 	int encrypt, flushed, len;
2373 	struct mppe_header {
2374 		uint16_t coher_cnt;
2375 		uint16_t protocol;
2376 	} __packed *hdr;
2377 	u_char *cp;
2378 	struct pipex_mppe *mppe;
2379 	struct mbuf *m;
2380 
2381 	mppe = &session->mppe_send;
2382 
2383 	/*
2384 	 * create a deep-copy if the mbuf has a shared mbuf cluster.
2385 	 * this is required to handle cases of tcp retransmission.
2386 	 */
2387 	for (m = m0; m != NULL; m = m->m_next) {
2388 		if (M_READONLY(m)) {
2389 			m = m_dup_pkt(m0, max_linkhdr, M_NOWAIT);
2390 			m_freem(m0);
2391 			if (m == NULL)
2392 				goto drop;
2393 			m0 = m;
2394 			break;
2395 		}
2396 	}
2397 	/* prepend mppe header */
2398 	M_PREPEND(m0, sizeof(struct mppe_header), M_NOWAIT);
2399 	if (m0 == NULL)
2400 		goto drop;
2401 	hdr = mtod(m0, struct mppe_header *);
2402 	hdr->protocol = protocol;
2403 
2404 	/* check coherency counter */
2405 	flushed = 0;
2406 	encrypt = 1;
2407 
2408 	mtx_enter(&mppe->pxm_mtx);
2409 
2410 	if (mppe->stateless != 0) {
2411 		flushed = 1;
2412 		mppe_key_change(mppe);
2413 	} else {
2414 		if ((mppe->coher_cnt % 0x100) == 0xff) {
2415 			flushed = 1;
2416 			mppe_key_change(mppe);
2417 		} else if (mppe->resetreq != 0) {
2418 			flushed = 1;
2419 			mppe->resetreq = 0;
2420 		}
2421 	}
2422 
2423 	if (flushed)
2424 		pipex_mppe_setkey(mppe);
2425 
2426 	PIPEX_MPPE_DBG((session, LOG_DEBUG, "out coher_cnt=%03x %s%s",
2427 	    mppe->coher_cnt, (flushed) ? "[flushed]" : "",
2428 	    (encrypt) ? "[encrypt]" : ""));
2429 
2430 	/* setup header information */
2431 	hdr->coher_cnt = (mppe->coher_cnt++) & PIPEX_COHERENCY_CNT_MASK;
2432 	hdr->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2433 	if (flushed)
2434 		hdr->coher_cnt |= 0x8000;
2435 	if (encrypt)
2436 		hdr->coher_cnt |= 0x1000;
2437 
2438 	hdr->protocol = htons(hdr->protocol);
2439 	hdr->coher_cnt = htons(hdr->coher_cnt);
2440 
2441 	/* encrypt chain */
2442 	for (m = m0; m; m = m->m_next) {
2443 		cp = mtod(m, u_char *);
2444 		len = m->m_len;
2445 		if (m == m0 && len > offsetof(struct mppe_header, protocol)) {
2446 			len -= offsetof(struct mppe_header, protocol);
2447 			cp += offsetof(struct mppe_header, protocol);
2448 		}
2449 		pipex_mppe_crypt(mppe, len, cp, cp);
2450 	}
2451 
2452 	mtx_leave(&mppe->pxm_mtx);
2453 
2454 	pipex_ppp_output(m0, session, PPP_COMP);
2455 
2456 	return;
2457 drop:
2458 	counters_inc(session->stat_counters, pxc_oerrors);
2459 }
2460 
2461 Static void
2462 pipex_ccp_input(struct mbuf *m0, struct pipex_session *session)
2463 {
2464 	u_char *cp;
2465 	int code, id, len;
2466 
2467 	if (m0->m_pkthdr.len < PPP_HDRLEN)
2468 		goto drop;
2469 	if ((m0 = m_pullup(m0, PPP_HDRLEN)) == NULL)
2470 		goto drop;
2471 
2472 	cp = mtod(m0, u_char *);
2473 	GETCHAR(code, cp);
2474 	GETCHAR(id, cp);
2475 	GETSHORT(len, cp);
2476 
2477 	switch (code) {
2478 	case CCP_RESETREQ:
2479 		PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetReq"));
2480 		mtx_enter(&session->mppe_send.pxm_mtx);
2481 		session->mppe_send.resetreq = 1;
2482 		mtx_leave(&session->mppe_send.pxm_mtx);
2483 #ifndef PIPEX_NO_CCP_RESETACK
2484 		PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetAck"));
2485 		pipex_ccp_output(session, CCP_RESETACK, id);
2486 #endif
2487 		/* ignore error */
2488 		break;
2489 	case CCP_RESETACK:
2490 		PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetAck"));
2491 		break;
2492 	default:
2493 		PIPEX_DBG((session, LOG_DEBUG, "CCP Recv code=%d", code));
2494 		goto drop;
2495 	}
2496 	m_freem(m0);
2497 
2498 	return;
2499 drop:
2500 	m_freem(m0);
2501 	counters_inc(session->stat_counters, pxc_ierrors);
2502 }
2503 
2504 Static int
2505 pipex_ccp_output(struct pipex_session *session, int code, int id)
2506 {
2507 	u_char *cp;
2508 	struct mbuf *m;
2509 
2510 	MGETHDR(m, M_DONTWAIT, MT_DATA);
2511 	if (m == NULL) {
2512 		counters_inc(session->stat_counters, pxc_oerrors);
2513 		return (1);
2514 	}
2515 	m->m_pkthdr.len = m->m_len = 4;
2516 	cp = mtod(m, u_char *);
2517 	PUTCHAR(code, cp);
2518 	PUTCHAR(id, cp);
2519 	PUTSHORT(4, cp);
2520 
2521 	pipex_ppp_output(m, session, PPP_CCP);
2522 
2523 	return (0);
2524 }
2525 #endif
2526 /***********************************************************************
2527  * Miscellaneous functions
2528  ***********************************************************************/
2529 /* adapted from FreeBSD:src/usr.sbin/ppp/tcpmss.c */
2530 /*
2531  * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org>
2532  * All rights reserved.
2533  *
2534  * Redistribution and use in source and binary forms, with or without
2535  * modification, are permitted provided that the following conditions
2536  * are met:
2537  * 1. Redistributions of source code must retain the above copyright
2538  *    notice, this list of conditions and the following disclaimer.
2539  * 2. Redistributions in binary form must reproduce the above copyright
2540  *    notice, this list of conditions and the following disclaimer in the
2541  *    documentation and/or other materials provided with the distribution.
2542  *
2543  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2544  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2545  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2546  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2547  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2548  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2549  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2550  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2551  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2552  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2553  * SUCH DAMAGE.
2554  *
2555  * $FreeBSD: src/usr.sbin/ppp/tcpmss.c,v 1.1.4.3 2001/07/19 11:39:54 brian Exp $
2556  */
2557 #define TCP_OPTLEN_IN_SEGMENT	12	/* timestamp option and padding */
2558 #define MAXMSS(mtu) (mtu - sizeof(struct ip) - sizeof(struct tcphdr) - \
2559     TCP_OPTLEN_IN_SEGMENT)
2560 /*
2561  * The following macro is used to update an internet checksum.  "acc" is a
2562  * 32-bit accumulation of all the changes to the checksum (adding in old
2563  * 16-bit words and subtracting out new words), and "cksum" is the checksum
2564  * value to be updated.
2565  */
2566 #define ADJUST_CHECKSUM(acc, cksum) {			\
2567 	acc += cksum;					\
2568 	if (acc < 0) {					\
2569 		acc = -acc;				\
2570 		acc = (acc >> 16) + (acc & 0xffff);	\
2571 		acc += acc >> 16;			\
2572 		cksum = (u_short) ~acc;			\
2573 	} else {					\
2574 		acc = (acc >> 16) + (acc & 0xffff);	\
2575 		acc += acc >> 16;			\
2576 		cksum = (u_short) acc;			\
2577 	}						\
2578 }
2579 
2580 /*
2581  * Rewrite max-segment-size TCP option to avoid PMTU blackhole issues.
2582  * The mtu parameter should be the MTU bottleneck (as far as we know)
2583  * on the link between the source and the destination.
2584  */
2585 Static struct mbuf *
2586 adjust_tcp_mss(struct mbuf *m0, int mtu)
2587 {
2588 	int opt, optlen, acc, mss, maxmss, lpktp;
2589 	struct ip *pip;
2590 	struct tcphdr *th;
2591 	u_char *pktp, *mssp;
2592 	u_int16_t ip_off;
2593 
2594 	lpktp = sizeof(struct ip) + sizeof(struct tcphdr) + PIPEX_TCP_OPTLEN;
2595 	lpktp = MIN(lpktp, m0->m_pkthdr.len);
2596 
2597 	PIPEX_PULLUP(m0, lpktp);
2598 	if (m0 == NULL)
2599 		goto drop;
2600 
2601 	pktp = mtod(m0, char *);
2602 	pip = (struct ip *)pktp;
2603 	ip_off = ntohs(pip->ip_off);
2604 
2605 	/* Non TCP or fragmented packet must not have a MSS option */
2606 	if (pip->ip_p != IPPROTO_TCP ||
2607 	    (ip_off & IP_MF) != 0 || (ip_off & IP_OFFMASK) != 0)
2608 		goto handled;
2609 
2610 	pktp += pip->ip_hl << 2;
2611 	lpktp -= pip->ip_hl << 2;
2612 
2613 	/* packet is broken */
2614 	if (sizeof(struct tcphdr) > lpktp)
2615 		goto drop;
2616 	th = (struct tcphdr *)pktp;
2617 
2618 	/*
2619 	 * As RFC 973, a MSS field must only be sent in the initial
2620 	 * connection request(it must be with SYN).
2621 	 */
2622 	if ((th->th_flags & TH_SYN) == 0)
2623 		goto handled;
2624 
2625 	lpktp = MIN(th->th_off << 4, lpktp);
2626 
2627 	pktp += sizeof(struct tcphdr);
2628 	lpktp -= sizeof(struct tcphdr);
2629 	while (lpktp >= TCPOLEN_MAXSEG) {
2630 		GETCHAR(opt, pktp);
2631 		switch (opt) {
2632 		case TCPOPT_MAXSEG:
2633 			GETCHAR(optlen, pktp);
2634 			mssp = pktp;		/* mss place holder */
2635 			GETSHORT(mss, pktp);
2636 			maxmss = MAXMSS(mtu);
2637 			if (mss > maxmss) {
2638 				PIPEX_DBG((NULL, LOG_DEBUG,
2639 				    "change tcp-mss %d => %d", mss, maxmss));
2640 				PUTSHORT(maxmss, mssp);
2641 				acc = htons(mss);
2642 				acc -= htons(maxmss);
2643 				ADJUST_CHECKSUM(acc, th->th_sum);
2644 			}
2645 			goto handled;
2646 			/* NOTREACHED */
2647 		case TCPOPT_EOL:
2648 			goto handled;
2649 			/* NOTREACHED */
2650 		case TCPOPT_NOP:
2651 			lpktp--;
2652 			break;
2653 		default:
2654 			GETCHAR(optlen, pktp);
2655 			if (optlen < 2)	/* packet is broken */
2656 				goto drop;
2657 			pktp += optlen - 2;
2658 			lpktp -= optlen;
2659 			break;
2660 		}
2661 	}
2662 
2663 handled:
2664 	return (m0);
2665 
2666 drop:
2667 	m_freem(m0);
2668 	return (NULL);
2669 }
2670 
2671 /*
2672  *  Check whether a packet should reset idle timer
2673  *  Returns 1 to don't reset timer (i.e. the packet is "idle" packet)
2674  */
2675 Static struct mbuf *
2676 ip_is_idle_packet(struct mbuf *m0, int *ris_idle)
2677 {
2678 	u_int16_t ip_off;
2679 	const struct udphdr *uh;
2680 	struct ip *pip;
2681 	int len;
2682 
2683 	/* pullup ip header */
2684 	len = sizeof(struct ip);
2685 	PIPEX_PULLUP(m0, len);
2686 	if (m0 == NULL)
2687 		goto error;
2688 	pip = mtod(m0, struct ip *);
2689 
2690 	/*
2691 	 * the packet which fragmentations was not the idle packet.
2692 	 */
2693 	ip_off = ntohs(pip->ip_off);
2694 	if ((ip_off & IP_MF) || ((ip_off & IP_OFFMASK) != 0))
2695 		goto is_active;
2696 
2697 	switch (pip->ip_p) {
2698 	case IPPROTO_IGMP:
2699 		goto is_active;
2700 	case IPPROTO_ICMP:
2701 		len = pip->ip_hl * 4 + 8;
2702 		PIPEX_PULLUP(m0, len);
2703 		if (m0 == NULL)
2704 			goto error;
2705 		pip = mtod(m0, struct ip *);
2706 
2707 		switch (((unsigned char *) pip)[pip->ip_hl * 4]) {
2708 		case 0:	/* Echo Reply */
2709 		case 8:	/* Echo Request */
2710 			goto is_active;
2711 		default:
2712 			goto is_idle;
2713 		}
2714 
2715 	case IPPROTO_UDP:
2716 	case IPPROTO_TCP:
2717 		len = pip->ip_hl * 4 + sizeof(struct udphdr);
2718 		PIPEX_PULLUP(m0, len);
2719 		if (m0 == NULL)
2720 			goto error;
2721 		pip = mtod(m0, struct ip *);
2722 		uh = (struct udphdr *)(mtod(m0, caddr_t) + pip->ip_hl * 4);
2723 
2724 		switch (ntohs(uh->uh_sport)) {
2725 		case 53:	/* DOMAIN */
2726 		case 67:	/* BOOTPS */
2727 		case 68:	/* BOOTPC */
2728 		case 123:	/* NTP */
2729 		case 137:	/* NETBIOS-NS */
2730 		case 520:	/* RIP */
2731 			goto is_idle;
2732 		}
2733 		switch (ntohs(uh->uh_dport)) {
2734 		case 53:	/* DOMAIN */
2735 		case 67:	/* BOOTPS */
2736 		case 68:	/* BOOTPC */
2737 		case 123:	/* NTP */
2738 		case 137:	/* NETBIOS-NS */
2739 		case 520:	/* RIP */
2740 			goto is_idle;
2741 		}
2742 		goto is_active;
2743 	default:
2744 		goto is_active;
2745 	}
2746 
2747 is_active:
2748 	*ris_idle = 0;
2749 	return (m0);
2750 
2751 is_idle:
2752 	*ris_idle = 1;
2753 	return (m0);
2754 
2755 error:
2756 	return (NULL);
2757 }
2758 
2759 Static void
2760 pipex_session_log(struct pipex_session *session, int prio, const char *fmt, ...)
2761 {
2762 	char logbuf[1024];
2763 	va_list ap;
2764 
2765 	logpri(prio);
2766 	if (session != NULL) {
2767 		struct ifnet *ifp;
2768 
2769 		ifp = if_get(session->ifindex);
2770 		addlog("pipex: ppp=%d iface=%s protocol=%s id=%d ",
2771 		    session->ppp_id,
2772 		    ifp? ifp->if_xname : "Unknown",
2773 		    (session->protocol == PIPEX_PROTO_PPPOE)? "PPPoE" :
2774 		    (session->protocol == PIPEX_PROTO_PPTP)? "PPTP" :
2775 		    (session->protocol == PIPEX_PROTO_L2TP) ? "L2TP" :
2776 		    "Unknown", session->session_id);
2777 		if_put(ifp);
2778 	} else
2779 		addlog("pipex: ");
2780 
2781 	va_start(ap, fmt);
2782 	vsnprintf(logbuf, sizeof(logbuf), fmt, ap);
2783 	va_end(ap);
2784 	addlog("%s\n", logbuf);
2785 }
2786 
2787 Static uint32_t
2788 pipex_sockaddr_hash_key(struct sockaddr *sa)
2789 {
2790 	switch (sa->sa_family) {
2791 	case AF_INET:
2792 		return ntohl(satosin(sa)->sin_addr.s_addr);
2793 	case AF_INET6:
2794 		return ntohl(satosin6(sa)->sin6_addr.s6_addr32[3]);
2795 	}
2796 	panic("pipex_sockaddr_hash_key: unknown address family");
2797 	return (0);
2798 }
2799 
2800 /*
2801  * Compare struct sockaddr_in{,6} with the address only.
2802  * The port number is not covered.
2803  */
2804 Static int
2805 pipex_sockaddr_compar_addr(struct sockaddr *a, struct sockaddr *b)
2806 {
2807 	int cmp;
2808 
2809 	cmp = b->sa_family - a->sa_family;
2810 	if (cmp != 0)
2811 		return cmp;
2812 	switch (a->sa_family) {
2813 	case AF_INET:
2814 		return (satosin(b)->sin_addr.s_addr -
2815 		    satosin(a)->sin_addr.s_addr);
2816 	case AF_INET6:
2817 		cmp = (satosin6(b)->sin6_scope_id - satosin6(a)->sin6_scope_id);
2818 		if (cmp != 0)
2819 			return cmp;
2820 		return (memcmp(&satosin6(a)->sin6_addr,
2821 		    &satosin6(b)->sin6_addr,
2822 		    sizeof(struct in6_addr)));
2823 	}
2824 	panic("pipex_sockaddr_compar_addr: unknown address family");
2825 
2826 	return (-1);
2827 }
2828 
2829 int
2830 pipex_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
2831     size_t newlen)
2832 {
2833 	switch (name[0]) {
2834 	case PIPEXCTL_ENABLE:
2835 		if (namelen != 1)
2836 			return (ENOTDIR);
2837 		return (sysctl_int_bounded(oldp, oldlenp, newp, newlen,
2838 		    &pipex_enable, 0, 1));
2839 	default:
2840 		return (ENOPROTOOPT);
2841 	}
2842 	/* NOTREACHED */
2843 }
2844