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