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