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