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