1 /* $OpenBSD: pipex.c,v 1.154 2024/06/07 13:43:21 jsg 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 #ifdef PIPEX_DEBUG
1511 if (session == NULL) {
1512 PIPEX_DBG((NULL, LOG_DEBUG,
1513 "<%s> session not found (id=%d)", __func__, id));
1514 goto not_ours;
1515 }
1516 #endif
1517
1518 return (session);
1519
1520 not_ours:
1521 return (NULL);
1522 }
1523
1524 struct mbuf *
pipex_pptp_input(struct mbuf * m0,struct pipex_session * session)1525 pipex_pptp_input(struct mbuf *m0, struct pipex_session *session)
1526 {
1527 int hlen, has_seq, has_ack, nseq;
1528 const char *reason = "";
1529 u_char *cp, *seqp = NULL, *ackp = NULL;
1530 uint32_t flags, seq = 0, ack = 0;
1531 struct ip *ip;
1532 struct pipex_gre_header *gre;
1533 struct pipex_pptp_session *pptp_session;
1534 int rewind = 0;
1535
1536 KASSERT(m0->m_pkthdr.len >= PIPEX_IPGRE_HDRLEN);
1537 pptp_session = &session->proto.pptp;
1538
1539 /* get ip header */
1540 ip = mtod(m0, struct ip *);
1541 hlen = ip->ip_hl << 2;
1542
1543 /* seek gre header */
1544 gre = PIPEX_SEEK_NEXTHDR(ip, hlen, struct pipex_gre_header *);
1545 flags = ntohs(gre->flags);
1546
1547 /* pullup for seek sequences in header */
1548 has_seq = (flags & PIPEX_GRE_SFLAG) ? 1 : 0;
1549 has_ack = (flags & PIPEX_GRE_AFLAG) ? 1 : 0;
1550 hlen = PIPEX_IPGRE_HDRLEN + 4 * (has_seq + has_ack);
1551 if (m0->m_len < hlen) {
1552 m0 = m_pullup(m0, hlen);
1553 if (m0 == NULL) {
1554 PIPEX_DBG((session, LOG_DEBUG, "pullup failed."));
1555 goto drop;
1556 }
1557 }
1558
1559 /* check sequence */
1560 cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
1561 if (has_seq) {
1562 seqp = cp;
1563 GETLONG(seq, cp);
1564 }
1565
1566 mtx_enter(&session->pxs_mtx);
1567
1568 if (has_ack) {
1569 ackp = cp;
1570 GETLONG(ack, cp);
1571 if (ack + 1 == pptp_session->snd_una) {
1572 /* ack has not changed before */
1573 } else if (SEQ32_LT(ack, pptp_session->snd_una)) {
1574 /* OoO ack packets should not be dropped. */
1575 rewind = 1;
1576 } else if (SEQ32_GT(ack, pptp_session->snd_nxt)) {
1577 reason = "ack for unknown sequence";
1578 goto out_seq;
1579 } else
1580 pptp_session->snd_una = ack + 1;
1581 }
1582 if (!has_seq) {
1583 /* ack only packet */
1584 goto not_ours;
1585 }
1586 if (SEQ32_LT(seq, pptp_session->rcv_nxt)) {
1587 rewind = 1;
1588 if (SEQ32_LT(seq,
1589 pptp_session->rcv_nxt - PIPEX_REWIND_LIMIT)) {
1590 reason = "out of sequence";
1591 goto out_seq;
1592 }
1593 } else if (SEQ32_GE(seq, pptp_session->rcv_nxt +
1594 pptp_session->maxwinsz)) {
1595 pipex_session_log(session, LOG_DEBUG,
1596 "received packet caused window overflow. seq=%u(%u-%u)"
1597 "may lost %d packets.", seq, pptp_session->rcv_nxt,
1598 pptp_session->rcv_nxt + pptp_session->maxwinsz,
1599 (int)SEQ32_SUB(seq, pptp_session->rcv_nxt));
1600 }
1601
1602 seq++;
1603 nseq = SEQ32_SUB(seq, pptp_session->rcv_nxt);
1604 if (!rewind) {
1605 pptp_session->rcv_nxt = seq;
1606 if (SEQ32_SUB(seq, pptp_session->rcv_acked) >
1607 roundup(pptp_session->winsz, 2) / 2) /* Send ack only packet. */
1608 pipex_pptp_output(NULL, session, 0, 1);
1609 }
1610
1611 /*
1612 * The following pipex_common_input() will release `pxs_mtx'
1613 * deep within if the packet will be consumed. In the error
1614 * path lock will be held all the time. So increment `rcv_gap'
1615 * here, and on the error path back it out, no atomicity will
1616 * be lost in all cases.
1617 */
1618 if (!rewind)
1619 session->proto.pptp.rcv_gap += nseq;
1620 m0 = pipex_common_input(session, m0, hlen, ntohs(gre->len), 1);
1621 if (m0 == NULL) {
1622 /*
1623 * pipex_common_input() releases lock if the
1624 * packet was consumed.
1625 */
1626 return (NULL);
1627 }
1628
1629 if (rewind)
1630 goto out_seq;
1631 else {
1632 /* The packet is not ours, back out `rcv_gap'. */
1633 session->proto.pptp.rcv_gap -= nseq;
1634 }
1635
1636 not_ours:
1637 seq--; /* revert original seq value */
1638
1639 /*
1640 * overwrite sequence numbers to adjust a gap between pipex and
1641 * userland.
1642 */
1643 if (seqp != NULL) {
1644 seq -= pptp_session->rcv_gap;
1645 PUTLONG(seq, seqp);
1646 }
1647 if (ackp != NULL) {
1648 if (pptp_session->snd_nxt == pptp_session->snd_una) {
1649 ack -= session->proto.pptp.snd_gap;
1650 pptp_session->ul_snd_una = ack;
1651 } else {
1652 /*
1653 * There are sending packets they are not acked.
1654 * In this situation, (ack - snd_gap) may points
1655 * before sending window of userland. So we don't
1656 * update the ack number.
1657 */
1658 ack = pptp_session->ul_snd_una;
1659 }
1660 PUTLONG(ack, ackp);
1661 }
1662
1663 mtx_leave(&session->pxs_mtx);
1664
1665 return (m0);
1666 out_seq:
1667 pipex_session_log(session, LOG_DEBUG,
1668 "Received bad data packet: %s: seq=%u(%u-%u) ack=%u(%u-%u)",
1669 reason, seq, pptp_session->rcv_nxt,
1670 pptp_session->rcv_nxt + pptp_session->maxwinsz,
1671 ack, pptp_session->snd_una,
1672 pptp_session->snd_nxt);
1673 mtx_leave(&session->pxs_mtx);
1674
1675 /* FALLTHROUGH */
1676 drop:
1677 m_freem(m0);
1678 counters_inc(session->stat_counters, pxc_ierrors);
1679
1680 return (NULL);
1681 }
1682
1683 struct pipex_session *
pipex_pptp_userland_lookup_session_ipv4(struct mbuf * m0,struct in_addr dst)1684 pipex_pptp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
1685 {
1686 struct sockaddr_in sin;
1687
1688 memset(&sin, 0, sizeof(sin));
1689 sin.sin_len = sizeof(sin);
1690 sin.sin_family = AF_INET;
1691 sin.sin_addr = dst;
1692
1693 return pipex_pptp_userland_lookup_session(m0, sintosa(&sin));
1694 }
1695
1696 #ifdef INET6
1697 struct pipex_session *
pipex_pptp_userland_lookup_session_ipv6(struct mbuf * m0,struct in6_addr dst)1698 pipex_pptp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
1699 {
1700 struct sockaddr_in6 sin6;
1701
1702 memset(&sin6, 0, sizeof(sin6));
1703 sin6.sin6_len = sizeof(sin6);
1704 sin6.sin6_family = AF_INET6;
1705 in6_recoverscope(&sin6, &dst);
1706
1707 return pipex_pptp_userland_lookup_session(m0, sin6tosa(&sin6));
1708 }
1709 #endif
1710
1711 struct pipex_session *
pipex_pptp_userland_lookup_session(struct mbuf * m0,struct sockaddr * sa)1712 pipex_pptp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
1713 {
1714 struct pipex_gre_header gre;
1715 struct pipex_hash_head *list;
1716 struct pipex_session *session;
1717 uint16_t id, flags;
1718
1719 /* pullup */
1720 if (m0->m_pkthdr.len < sizeof(gre)) {
1721 PIPEX_DBG((NULL, LOG_DEBUG,
1722 "<%s> packet length is too short", __func__));
1723 return (NULL);
1724 }
1725
1726 /* get flags */
1727 m_copydata(m0, 0, sizeof(struct pipex_gre_header), &gre);
1728 flags = ntohs(gre.flags);
1729
1730 /* gre version must be '1' */
1731 if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
1732 PIPEX_DBG((NULL, LOG_DEBUG,
1733 "<%s> gre header wrong version.", __func__));
1734 return (NULL);
1735 }
1736
1737 /* gre keys must be present */
1738 if ((flags & PIPEX_GRE_KFLAG) == 0) {
1739 PIPEX_DBG((NULL, LOG_DEBUG,
1740 "<%s> gre header has no keys.", __func__));
1741 return (NULL);
1742 }
1743
1744 /* lookup pipex session table */
1745 id = ntohs(gre.call_id);
1746
1747 mtx_enter(&pipex_list_mtx);
1748
1749 list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
1750 LIST_FOREACH(session, list, peer_addr_chain) {
1751 if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
1752 continue;
1753 if (session->peer_session_id == id)
1754 break;
1755 }
1756
1757 if (session != NULL)
1758 refcnt_take(&session->pxs_refcnt);
1759
1760 mtx_leave(&pipex_list_mtx);
1761
1762 #ifdef PIPEX_DEBUG
1763 if (session == NULL) {
1764 PIPEX_DBG((NULL, LOG_DEBUG,
1765 "<%s> session not found (,call_id=%d)",
1766 __func__, (int)gre.call_id));
1767 }
1768 #endif
1769 return (session);
1770 }
1771
1772 /*
1773 * pipex_pptp_userland_output
1774 */
1775 struct mbuf *
pipex_pptp_userland_output(struct mbuf * m0,struct pipex_session * session)1776 pipex_pptp_userland_output(struct mbuf *m0, struct pipex_session *session)
1777 {
1778 int len;
1779 struct pipex_gre_header *gre, gre0;
1780 uint16_t flags;
1781 u_char *cp, *cp0;
1782 uint32_t val32;
1783
1784 len = sizeof(struct pipex_gre_header);
1785 m_copydata(m0, 0, len, &gre0);
1786 gre = &gre0;
1787 flags = ntohs(gre->flags);
1788 if ((flags & PIPEX_GRE_SFLAG) != 0)
1789 len += 4;
1790 if ((flags & PIPEX_GRE_AFLAG) != 0)
1791 len += 4;
1792
1793 /* check length */
1794 PIPEX_PULLUP(m0, len);
1795 if (m0 == NULL) {
1796 PIPEX_DBG((session, LOG_DEBUG, "gre header is too short."));
1797 return (NULL);
1798 }
1799
1800 gre = mtod(m0, struct pipex_gre_header *);
1801 cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header), u_char *);
1802
1803 mtx_enter(&session->pxs_mtx);
1804
1805 /*
1806 * overwrite sequence numbers to adjust a gap between pipex and
1807 * userland.
1808 */
1809 if ((flags & PIPEX_GRE_SFLAG) != 0) {
1810 cp0 = cp;
1811 GETLONG(val32, cp);
1812 val32 += session->proto.pptp.snd_gap;
1813 PUTLONG(val32, cp0);
1814 session->proto.pptp.snd_nxt++;
1815 }
1816 if ((flags & PIPEX_GRE_AFLAG) != 0) {
1817 cp0 = cp;
1818 GETLONG(val32, cp);
1819 val32 += session->proto.pptp.rcv_gap;
1820 PUTLONG(val32, cp0);
1821 if (SEQ32_GT(val32, session->proto.pptp.rcv_acked))
1822 session->proto.pptp.rcv_acked = val32;
1823 }
1824
1825 mtx_leave(&session->pxs_mtx);
1826
1827 return (m0);
1828 }
1829 #endif /* PIPEX_PPTP */
1830
1831 #ifdef PIPEX_L2TP
1832 /***********************************************************************
1833 * L2TP support
1834 ***********************************************************************/
1835 void
pipex_l2tp_output(struct mbuf * m0,struct pipex_session * session)1836 pipex_l2tp_output(struct mbuf *m0, struct pipex_session *session)
1837 {
1838 int hlen, plen, datalen;
1839 struct pipex_l2tp_header *l2tp = NULL;
1840 struct pipex_l2tp_seq_header *seq = NULL;
1841 struct udphdr *udp;
1842 struct ip *ip;
1843 #ifdef INET6
1844 struct ip6_hdr *ip6;
1845 #endif
1846 struct m_tag *mtag;
1847
1848 hlen = sizeof(struct pipex_l2tp_header) +
1849 ((pipex_session_is_l2tp_data_sequencing_on(session))
1850 ? sizeof(struct pipex_l2tp_seq_header) : 0) +
1851 sizeof(struct udphdr) +
1852 #ifdef INET6
1853 ((session->peer.sin6.sin6_family == AF_INET6)
1854 ? sizeof(struct ip6_hdr) : sizeof(struct ip));
1855 #else
1856 sizeof(struct ip);
1857 #endif
1858
1859 datalen = 0;
1860 if (m0 != NULL) {
1861 datalen = m0->m_pkthdr.len;
1862 M_PREPEND(m0, hlen, M_NOWAIT);
1863 if (m0 == NULL)
1864 goto drop;
1865 } else {
1866 MGETHDR(m0, M_DONTWAIT, MT_DATA);
1867 if (m0 == NULL)
1868 goto drop;
1869 KASSERT(hlen <= MHLEN);
1870 m0->m_pkthdr.len = m0->m_len = hlen;
1871 }
1872
1873 #ifdef INET6
1874 hlen = (session->peer.sin6.sin6_family == AF_INET6)
1875 ? sizeof(struct ip6_hdr) : sizeof(struct ip);
1876 #else
1877 hlen = sizeof(struct ip);
1878 #endif
1879 plen = datalen + sizeof(struct pipex_l2tp_header) +
1880 ((pipex_session_is_l2tp_data_sequencing_on(session))
1881 ? sizeof(struct pipex_l2tp_seq_header) : 0);
1882
1883 l2tp = (struct pipex_l2tp_header *)
1884 (mtod(m0, caddr_t) + hlen + sizeof(struct udphdr));
1885 l2tp->flagsver = PIPEX_L2TP_VER | PIPEX_L2TP_FLAG_LENGTH;
1886 l2tp->length = htons(plen);
1887 l2tp->tunnel_id = htons(session->proto.l2tp.peer_tunnel_id);
1888 l2tp->session_id = htons(session->peer_session_id);
1889 if (pipex_session_is_l2tp_data_sequencing_on(session)) {
1890 seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
1891 l2tp->flagsver |= PIPEX_L2TP_FLAG_SEQUENCE;
1892
1893 mtx_enter(&session->pxs_mtx);
1894 seq->ns = htons(session->proto.l2tp.ns_nxt);
1895 session->proto.l2tp.ns_nxt++;
1896 session->proto.l2tp.ns_gap++;
1897 session->proto.l2tp.nr_acked = session->proto.l2tp.nr_nxt - 1;
1898 seq->nr = htons(session->proto.l2tp.nr_acked);
1899 mtx_leave(&session->pxs_mtx);
1900 }
1901 l2tp->flagsver = htons(l2tp->flagsver);
1902
1903 plen += sizeof(struct udphdr);
1904 udp = (struct udphdr *)(mtod(m0, caddr_t) + hlen);
1905 udp->uh_sport = session->local.sin6.sin6_port;
1906 udp->uh_dport = session->peer.sin6.sin6_port;
1907 udp->uh_ulen = htons(plen);
1908 udp->uh_sum = 0;
1909
1910 m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
1911 m0->m_pkthdr.ph_ifidx = session->ifindex;
1912 #if NPF > 0
1913 pf_pkt_addr_changed(m0);
1914 #endif
1915 switch (session->peer.sin6.sin6_family) {
1916 case AF_INET:
1917 ip = mtod(m0, struct ip *);
1918 ip->ip_p = IPPROTO_UDP;
1919 ip->ip_src = session->local.sin4.sin_addr;
1920 ip->ip_dst = session->peer.sin4.sin_addr;
1921 ip->ip_len = htons(hlen + plen);
1922 ip->ip_ttl = MAXTTL;
1923 ip->ip_tos = 0;
1924 ip->ip_off = 0;
1925
1926 mtx_enter(&session->pxs_mtx);
1927 if (session->proto.l2tp.ipsecflowinfo > 0) {
1928 if ((mtag = m_tag_get(PACKET_TAG_IPSEC_FLOWINFO,
1929 sizeof(u_int32_t), M_NOWAIT)) == NULL) {
1930 mtx_leave(&session->pxs_mtx);
1931 goto drop;
1932 }
1933
1934 *(u_int32_t *)(mtag + 1) =
1935 session->proto.l2tp.ipsecflowinfo;
1936 m_tag_prepend(m0, mtag);
1937 }
1938 mtx_leave(&session->pxs_mtx);
1939
1940 ip_send(m0);
1941 break;
1942 #ifdef INET6
1943 case AF_INET6:
1944 ip6 = mtod(m0, struct ip6_hdr *);
1945
1946 ip6->ip6_flow = 0;
1947 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
1948 ip6->ip6_vfc |= IPV6_VERSION;
1949 ip6->ip6_nxt = IPPROTO_UDP;
1950 ip6->ip6_src = session->local.sin6.sin6_addr;
1951 in6_embedscope(&ip6->ip6_dst, &session->peer.sin6, NULL, NULL);
1952 /* ip6->ip6_plen will be filled in ip6_output. */
1953
1954 ip6_send(m0);
1955 break;
1956 #endif
1957 }
1958 udpstat_inc(udps_opackets);
1959
1960 if (datalen > 0) { /* network layer only */
1961 /* countup statistics */
1962 counters_pkt(session->stat_counters, pxc_opackets,
1963 pxc_obytes, datalen);
1964 }
1965
1966 return;
1967 drop:
1968 m_freem(m0);
1969 counters_inc(session->stat_counters, pxc_oerrors);
1970 }
1971
1972 struct pipex_session *
pipex_l2tp_lookup_session(struct mbuf * m0,int off)1973 pipex_l2tp_lookup_session(struct mbuf *m0, int off)
1974 {
1975 struct pipex_session *session;
1976 uint16_t flags, session_id, ver;
1977 u_char *cp, buf[PIPEX_L2TP_MINLEN];
1978
1979 if (m0->m_pkthdr.len < off + PIPEX_L2TP_MINLEN) {
1980 PIPEX_DBG((NULL, LOG_DEBUG,
1981 "<%s> packet length is too short", __func__));
1982 goto not_ours;
1983 }
1984
1985 /* get first 16bits of L2TP */
1986 m_copydata(m0, off, sizeof(buf), buf);
1987 cp = buf;
1988 GETSHORT(flags, cp);
1989 ver = flags & PIPEX_L2TP_VER_MASK;
1990
1991 /* l2tp version must be '2' */
1992 if (ver != PIPEX_L2TP_VER) {
1993 PIPEX_DBG((NULL, LOG_DEBUG,
1994 "<%s> l2tp header wrong version %u.", __func__, ver));
1995 goto not_ours;
1996 }
1997 if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
1998 goto not_ours;
1999
2000 if (flags & PIPEX_L2TP_FLAG_LENGTH)
2001 cp += 2; /* skip length field */
2002 cp += 2; /* skip tunnel-id field */
2003 GETSHORT(session_id, cp); /* get session-id field */
2004
2005 /* lookup pipex session table */
2006 session = pipex_lookup_by_session_id(PIPEX_PROTO_L2TP, session_id);
2007 #ifdef PIPEX_DEBUG
2008 if (session == NULL) {
2009 PIPEX_DBG((NULL, LOG_DEBUG,
2010 "<%s> session not found (id=%d)", __func__, session_id));
2011 goto not_ours;
2012 }
2013 #endif
2014
2015 return (session);
2016
2017 not_ours:
2018 return (NULL);
2019 }
2020
2021 struct mbuf *
pipex_l2tp_input(struct mbuf * m0,int off0,struct pipex_session * session,uint32_t ipsecflowinfo)2022 pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session,
2023 uint32_t ipsecflowinfo)
2024 {
2025 struct pipex_l2tp_session *l2tp_session;
2026 int length = 0, offset = 0, hlen, nseq;
2027 u_char *cp, *nsp = NULL, *nrp = NULL;
2028 uint16_t flags, ns = 0, nr = 0;
2029 int rewind = 0;
2030
2031 mtx_enter(&session->pxs_mtx);
2032
2033 l2tp_session = &session->proto.l2tp;
2034 l2tp_session->ipsecflowinfo = ipsecflowinfo;
2035
2036 m_copydata(m0, off0, sizeof(flags), &flags);
2037
2038 flags = ntohs(flags) & PIPEX_L2TP_FLAG_MASK;
2039 KASSERT((flags & PIPEX_L2TP_FLAG_TYPE) == 0);
2040
2041 hlen = 2; /* flags and version fields */
2042 if (flags & PIPEX_L2TP_FLAG_LENGTH) /* length */
2043 hlen += 2;
2044 hlen += 4; /* tunnel-id and session-id */
2045 if (flags & PIPEX_L2TP_FLAG_SEQUENCE) /* ns and nr */
2046 hlen += 4;
2047 if (flags & PIPEX_L2TP_FLAG_OFFSET) /* offset */
2048 hlen += 2;
2049
2050 PIPEX_PULLUP(m0, off0 + hlen);
2051 if (m0 == NULL)
2052 goto drop;
2053
2054 cp = mtod(m0, u_char *) + off0;
2055 cp += 2; /* flags and version */
2056 if (flags & PIPEX_L2TP_FLAG_LENGTH)
2057 GETSHORT(length, cp);
2058 else
2059 length = m0->m_pkthdr.len - off0;
2060 cp += 4; /* skip tunnel-id and session-id field */
2061
2062 /* pullup for seek sequences in header */
2063 nseq = 0;
2064 if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
2065 nsp = cp;
2066 GETSHORT(ns, cp);
2067 nrp = cp;
2068 GETSHORT(nr, cp);
2069
2070 nr++;
2071 if (SEQ16_GT(nr, l2tp_session->ns_una) &&
2072 SEQ16_LE(nr, l2tp_session->ns_nxt))
2073 /* update 'ns_una' only if the ns is in valid range */
2074 l2tp_session->ns_una = nr;
2075 if (SEQ16_LT(ns, l2tp_session->nr_nxt)) {
2076 rewind = 1;
2077 if (SEQ16_LT(ns,
2078 l2tp_session->nr_nxt - PIPEX_REWIND_LIMIT))
2079 goto out_seq;
2080 }
2081
2082 ns++;
2083 nseq = SEQ16_SUB(ns, l2tp_session->nr_nxt);
2084 if (!rewind)
2085 l2tp_session->nr_nxt = ns;
2086 }
2087 if (flags & PIPEX_L2TP_FLAG_OFFSET)
2088 GETSHORT(offset, cp);
2089
2090 length -= hlen + offset;
2091 hlen += off0 + offset;
2092
2093 /*
2094 * The following pipex_common_input() will release `pxs_mtx'
2095 * deep within if the packet will be consumed. In the error
2096 * path lock will be held all the time. So increment `nr_gap'
2097 * here, and on the error path back it out, no atomicity will
2098 * be lost in all cases.
2099 */
2100 if (!rewind)
2101 session->proto.l2tp.nr_gap += nseq;
2102 m0 = pipex_common_input(session, m0, hlen, length, 1);
2103 if (m0 == NULL) {
2104 /*
2105 * pipex_common_input() releases lock if the
2106 * packet was consumed.
2107 */
2108 return (NULL);
2109 }
2110
2111 if (rewind)
2112 goto out_seq;
2113 else {
2114 /* The packet is not ours, backout `nr_gap'. */
2115 session->proto.l2tp.nr_gap -= nseq;
2116 }
2117
2118 /*
2119 * overwrite sequence numbers to adjust a gap between pipex and
2120 * userland.
2121 */
2122 if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
2123 --ns; --nr; /* revert original values */
2124 ns -= l2tp_session->nr_gap;
2125 PUTSHORT(ns, nsp);
2126
2127 if (l2tp_session->ns_nxt == l2tp_session->ns_una) {
2128 nr -= l2tp_session->ns_gap;
2129 l2tp_session->ul_ns_una = nr;
2130 } else {
2131 /*
2132 * There are sending packets they are not acked.
2133 * In this situation, (ack - snd_gap) may points
2134 * before sending window of userland. So we don't
2135 * update the ack number.
2136 */
2137 nr = l2tp_session->ul_ns_una;
2138 }
2139 PUTSHORT(nr, nrp);
2140 }
2141
2142 mtx_leave(&session->pxs_mtx);
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 /* FALLTHROUGH */
2151 drop:
2152 mtx_leave(&session->pxs_mtx);
2153
2154 m_freem(m0);
2155 counters_inc(session->stat_counters, pxc_ierrors);
2156
2157 return (NULL);
2158 }
2159
2160 struct pipex_session *
pipex_l2tp_userland_lookup_session_ipv4(struct mbuf * m0,struct in_addr dst)2161 pipex_l2tp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
2162 {
2163 struct sockaddr_in sin;
2164
2165 memset(&sin, 0, sizeof(sin));
2166 sin.sin_len = sizeof(sin);
2167 sin.sin_family = AF_INET;
2168 sin.sin_addr = dst;
2169
2170 return pipex_l2tp_userland_lookup_session(m0, sintosa(&sin));
2171 }
2172
2173 #ifdef INET6
2174 struct pipex_session *
pipex_l2tp_userland_lookup_session_ipv6(struct mbuf * m0,struct in6_addr dst)2175 pipex_l2tp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
2176 {
2177 struct sockaddr_in6 sin6;
2178
2179 memset(&sin6, 0, sizeof(sin6));
2180 sin6.sin6_len = sizeof(sin6);
2181 sin6.sin6_family = AF_INET6;
2182 in6_recoverscope(&sin6, &dst);
2183
2184 return pipex_l2tp_userland_lookup_session(m0, sin6tosa(&sin6));
2185 }
2186 #endif
2187
2188 struct pipex_session *
pipex_l2tp_userland_lookup_session(struct mbuf * m0,struct sockaddr * sa)2189 pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
2190 {
2191 struct pipex_l2tp_header l2tp;
2192 struct pipex_hash_head *list;
2193 struct pipex_session *session;
2194 uint16_t session_id, tunnel_id, flags;
2195
2196 if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
2197 return (NULL);
2198
2199 /* pullup */
2200 if (m0->m_pkthdr.len < sizeof(l2tp)) {
2201 PIPEX_DBG((NULL, LOG_DEBUG,
2202 "<%s> packet length is too short", __func__));
2203 return (NULL);
2204 }
2205
2206 /* get flags */
2207 m_copydata(m0, 0, sizeof(l2tp), &l2tp);
2208 flags = ntohs(l2tp.flagsver);
2209
2210 /* l2tp version must be '2' */
2211 if ((flags & PIPEX_L2TP_VER_MASK) != PIPEX_L2TP_VER) {
2212 PIPEX_DBG((NULL, LOG_DEBUG,
2213 "<%s> l2tp header wrong version.", __func__));
2214 return (NULL);
2215 }
2216 /* We need L2TP data messages only */
2217 if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
2218 return (NULL);
2219 /* No need to hook packets that don't have the sequence field */
2220 if ((flags & PIPEX_L2TP_FLAG_SEQUENCE) == 0)
2221 return (NULL);
2222
2223 session_id = ntohs(l2tp.session_id);
2224 tunnel_id = ntohs(l2tp.tunnel_id);
2225
2226 mtx_enter(&pipex_list_mtx);
2227
2228 list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
2229 LIST_FOREACH(session, list, peer_addr_chain) {
2230 if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
2231 continue;
2232 if (session->proto.l2tp.peer_tunnel_id != tunnel_id)
2233 continue;
2234 if (session->peer_session_id == session_id)
2235 break;
2236 }
2237
2238 if (session != NULL)
2239 refcnt_take(&session->pxs_refcnt);
2240
2241 mtx_leave(&pipex_list_mtx);
2242
2243 #ifdef PIPEX_DEBUG
2244 if (session == NULL) {
2245 PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found "
2246 "(tunnel_id=%d, session_id=%d)", __func__,
2247 tunnel_id, session_id));
2248 }
2249 #endif
2250
2251 return (session);
2252 }
2253
2254 struct mbuf *
pipex_l2tp_userland_output(struct mbuf * m0,struct pipex_session * session)2255 pipex_l2tp_userland_output(struct mbuf *m0, struct pipex_session *session)
2256 {
2257 struct pipex_l2tp_header *l2tp;
2258 struct pipex_l2tp_seq_header *seq;
2259 uint16_t ns, nr;
2260
2261 /* check length */
2262 PIPEX_PULLUP(m0, sizeof(struct pipex_l2tp_header) +
2263 sizeof(struct pipex_l2tp_seq_header));
2264 if (m0 == NULL)
2265 return (NULL);
2266
2267 l2tp = mtod(m0, struct pipex_l2tp_header *);
2268 KASSERT(ntohs(l2tp->flagsver) & PIPEX_L2TP_FLAG_SEQUENCE);
2269
2270 /*
2271 * overwrite sequence numbers to adjust a gap between pipex and
2272 * userland.
2273 */
2274 seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
2275 ns = ntohs(seq->ns);
2276 nr = ntohs(seq->nr);
2277
2278 mtx_enter(&session->pxs_mtx);
2279
2280 ns += session->proto.l2tp.ns_gap;
2281 seq->ns = htons(ns);
2282 session->proto.l2tp.ns_nxt++;
2283
2284 nr += session->proto.l2tp.nr_gap;
2285 seq->nr = htons(nr);
2286 if (SEQ16_GT(nr, session->proto.l2tp.nr_acked))
2287 session->proto.l2tp.nr_acked = nr;
2288
2289 mtx_leave(&session->pxs_mtx);
2290
2291 return (m0);
2292 }
2293 #endif /* PIPEX_L2TP */
2294
2295 #ifdef PIPEX_MPPE
2296 /**********************************************************************
2297 * MPPE
2298 ***********************************************************************/
2299 #define PIPEX_COHERENCY_CNT_MASK 0x0fff
2300
2301 static inline int
pipex_mppe_setkey(struct pipex_mppe * mppe)2302 pipex_mppe_setkey(struct pipex_mppe *mppe)
2303 {
2304 rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen);
2305
2306 return (0);
2307 }
2308
2309 static inline int
pipex_mppe_setoldkey(struct pipex_mppe * mppe,uint16_t coher_cnt)2310 pipex_mppe_setoldkey(struct pipex_mppe *mppe, uint16_t coher_cnt)
2311 {
2312 KASSERT(mppe->old_session_keys != NULL);
2313
2314 rc4_keysetup(&mppe->rc4ctx,
2315 mppe->old_session_keys[coher_cnt & PIPEX_MPPE_OLDKEYMASK],
2316 mppe->keylen);
2317
2318 return (0);
2319 }
2320
2321 static inline void
pipex_mppe_crypt(struct pipex_mppe * mppe,int len,u_char * indata,u_char * outdata)2322 pipex_mppe_crypt(struct pipex_mppe *mppe, int len, u_char *indata,
2323 u_char *outdata)
2324 {
2325 rc4_crypt(&mppe->rc4ctx, indata, outdata, len);
2326 }
2327
2328 void
pipex_mppe_init(struct pipex_mppe * mppe,int stateless,int keylenbits,u_char * master_key,int has_oldkey)2329 pipex_mppe_init(struct pipex_mppe *mppe, int stateless, int keylenbits,
2330 u_char *master_key, int has_oldkey)
2331 {
2332 memset(mppe, 0, sizeof(struct pipex_mppe));
2333 mtx_init(&mppe->pxm_mtx, IPL_SOFTNET);
2334 if (stateless)
2335 mppe->flags |= PIPEX_MPPE_STATELESS;
2336 if (has_oldkey)
2337 mppe->old_session_keys =
2338 pool_get(&mppe_key_pool, PR_WAITOK);
2339 else
2340 mppe->old_session_keys = NULL;
2341 memcpy(mppe->master_key, master_key, sizeof(mppe->master_key));
2342
2343 mppe->keylenbits = keylenbits;
2344 switch (keylenbits) {
2345 case 40:
2346 case 56:
2347 mppe->keylen = 8;
2348 break;
2349 case 128:
2350 mppe->keylen = 16;
2351 break;
2352 }
2353
2354 GetNewKeyFromSHA(mppe->master_key, mppe->master_key, mppe->keylen,
2355 mppe->session_key);
2356 pipex_mppe_reduce_key(mppe);
2357 pipex_mppe_setkey(mppe);
2358 }
2359
2360 void
pipex_session_init_mppe_recv(struct pipex_session * session,int stateless,int keylenbits,u_char * master_key)2361 pipex_session_init_mppe_recv(struct pipex_session *session, int stateless,
2362 int keylenbits, u_char *master_key)
2363 {
2364 pipex_mppe_init(&session->mppe_recv, stateless, keylenbits,
2365 master_key, stateless);
2366 session->ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED;
2367 }
2368
2369 void
pipex_session_init_mppe_send(struct pipex_session * session,int stateless,int keylenbits,u_char * master_key)2370 pipex_session_init_mppe_send(struct pipex_session *session, int stateless,
2371 int keylenbits, u_char *master_key)
2372 {
2373 pipex_mppe_init(&session->mppe_send, stateless, keylenbits,
2374 master_key, 0);
2375 session->ppp_flags |= PIPEX_PPP_MPPE_ENABLED;
2376 }
2377
2378 #include <crypto/sha1.h>
2379
2380 static u_char SHAPad1[] = {
2381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2386 }, SHAPad2[] = {
2387 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2388 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2389 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2390 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2391 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
2392 };
2393
2394 void
GetNewKeyFromSHA(u_char * StartKey,u_char * SessionKey,int SessionKeyLength,u_char * InterimKey)2395 GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength,
2396 u_char *InterimKey)
2397 {
2398 u_char Digest[20];
2399 SHA1_CTX Context;
2400
2401 SHA1Init(&Context);
2402 SHA1Update(&Context, StartKey, SessionKeyLength);
2403 SHA1Update(&Context, SHAPad1, 40);
2404 SHA1Update(&Context, SessionKey, SessionKeyLength);
2405 SHA1Update(&Context, SHAPad2, 40);
2406 SHA1Final(Digest, &Context);
2407
2408 memcpy(InterimKey, Digest, SessionKeyLength);
2409 }
2410
2411 void
pipex_mppe_reduce_key(struct pipex_mppe * mppe)2412 pipex_mppe_reduce_key(struct pipex_mppe *mppe)
2413 {
2414 switch (mppe->keylenbits) {
2415 case 40:
2416 mppe->session_key[0] = 0xd1;
2417 mppe->session_key[1] = 0x26;
2418 mppe->session_key[2] = 0x9e;
2419 break;
2420 case 56:
2421 mppe->session_key[0] = 0xd1;
2422 break;
2423 }
2424 }
2425
2426 void
mppe_key_change(struct pipex_mppe * mppe)2427 mppe_key_change(struct pipex_mppe *mppe)
2428 {
2429 u_char interim[16];
2430 struct rc4_ctx keychg;
2431
2432 memset(&keychg, 0, sizeof(keychg));
2433
2434 GetNewKeyFromSHA(mppe->master_key, mppe->session_key, mppe->keylen,
2435 interim);
2436
2437 rc4_keysetup(&keychg, interim, mppe->keylen);
2438 rc4_crypt(&keychg, interim, mppe->session_key, mppe->keylen);
2439
2440 pipex_mppe_reduce_key(mppe);
2441
2442 if (mppe->old_session_keys) {
2443 int idx = mppe->coher_cnt & PIPEX_MPPE_OLDKEYMASK;
2444 memcpy(mppe->old_session_keys[idx],
2445 mppe->session_key, PIPEX_MPPE_KEYLEN);
2446 }
2447 }
2448
2449 struct mbuf *
pipex_mppe_input(struct mbuf * m0,struct pipex_session * session)2450 pipex_mppe_input(struct mbuf *m0, struct pipex_session *session)
2451 {
2452 int pktloss, encrypt, flushed, m, n, len;
2453 struct pipex_mppe *mppe;
2454 uint16_t coher_cnt;
2455 struct mbuf *m1;
2456 u_char *cp;
2457 int rewind = 0;
2458
2459 /* pullup */
2460 PIPEX_PULLUP(m0, sizeof(coher_cnt));
2461 if (m0 == NULL)
2462 goto drop;
2463
2464 mppe = &session->mppe_recv;
2465 /* get header information */
2466 cp = mtod(m0, u_char *);
2467 GETSHORT(coher_cnt, cp);
2468 flushed = ((coher_cnt & 0x8000) != 0) ? 1 : 0;
2469 encrypt = ((coher_cnt & 0x1000) != 0) ? 1 : 0;
2470 coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2471 pktloss = 0;
2472
2473 mtx_enter(&mppe->pxm_mtx);
2474
2475 PIPEX_MPPE_DBG((session, LOG_DEBUG, "in coher_cnt=%03x %s%s",
2476 mppe->coher_cnt, (flushed) ? "[flushed]" : "",
2477 (encrypt) ? "[encrypt]" : ""));
2478
2479 if (encrypt == 0) {
2480 mtx_leave(&mppe->pxm_mtx);
2481 pipex_session_log(session, LOG_DEBUG,
2482 "Received unexpected MPPE packet.(no ecrypt)");
2483 goto drop;
2484 }
2485
2486 /* adjust mbuf */
2487 m_adj(m0, sizeof(coher_cnt));
2488
2489 /*
2490 * L2TP data session may be used without sequencing, PPP frames may
2491 * arrive in disorder. The 'coherency counter' of MPPE detects such
2492 * situations, but we cannot distinguish between 'disorder' and
2493 * 'packet loss' exactly.
2494 *
2495 * When 'coherency counter' detects lost packets greater than
2496 * (4096 - 256), we treat as 'disorder' otherwise treat as
2497 * 'packet loss'.
2498 */
2499 {
2500 int coher_cnt0;
2501
2502 coher_cnt0 = coher_cnt;
2503 if (coher_cnt < mppe->coher_cnt)
2504 coher_cnt0 += 0x1000;
2505 if (coher_cnt0 - mppe->coher_cnt > 0x0f00) {
2506 if ((mppe->flags & PIPEX_MPPE_STATELESS) == 0 ||
2507 coher_cnt0 - mppe->coher_cnt
2508 <= 0x1000 - PIPEX_MPPE_NOLDKEY) {
2509 pipex_session_log(session, LOG_DEBUG,
2510 "Workaround the out-of-sequence PPP framing problem: "
2511 "%d => %d", mppe->coher_cnt, coher_cnt);
2512 mtx_leave(&mppe->pxm_mtx);
2513 goto drop;
2514 }
2515 rewind = 1;
2516 }
2517 }
2518
2519 if ((mppe->flags & PIPEX_MPPE_STATELESS) != 0) {
2520 if (!rewind) {
2521 mppe_key_change(mppe);
2522 while (mppe->coher_cnt != coher_cnt) {
2523 mppe->coher_cnt++;
2524 mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2525 mppe_key_change(mppe);
2526 pktloss++;
2527 }
2528 }
2529 pipex_mppe_setoldkey(mppe, coher_cnt);
2530 } else {
2531 if (flushed) {
2532 if (coher_cnt < mppe->coher_cnt) {
2533 coher_cnt += 0x1000;
2534 }
2535 pktloss += coher_cnt - mppe->coher_cnt;
2536 m = mppe->coher_cnt / 256;
2537 n = coher_cnt / 256;
2538 while (m++ < n)
2539 mppe_key_change(mppe);
2540
2541 coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2542 mppe->coher_cnt = coher_cnt;
2543 } else if (mppe->coher_cnt != coher_cnt) {
2544 int ccp_id;
2545
2546 mtx_leave(&mppe->pxm_mtx);
2547
2548 /* Send CCP ResetReq */
2549 PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetReq"));
2550
2551 mtx_enter(&session->pxs_mtx);
2552 ccp_id = session->ccp_id;
2553 session->ccp_id++;
2554 mtx_leave(&session->pxs_mtx);
2555
2556 pipex_ccp_output(session, CCP_RESETREQ, ccp_id);
2557 goto drop;
2558 }
2559 if ((coher_cnt & 0xff) == 0xff) {
2560 mppe_key_change(mppe);
2561 flushed = 1;
2562 }
2563 if (flushed)
2564 pipex_mppe_setkey(mppe);
2565 }
2566
2567 if (pktloss > 1000) {
2568 pipex_session_log(session, LOG_DEBUG,
2569 "%d packets loss.", pktloss);
2570 }
2571
2572 /* decrypt ppp payload */
2573 for (m1 = m0; m1; m1 = m1->m_next) {
2574 cp = mtod(m1, u_char *);
2575 len = m1->m_len;
2576 pipex_mppe_crypt(mppe, len, cp, cp);
2577 }
2578
2579 if (!rewind) {
2580 /* update coher_cnt */
2581 mppe->coher_cnt++;
2582 mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2583 }
2584
2585 mtx_leave(&mppe->pxm_mtx);
2586
2587 if (m0->m_pkthdr.len < PIPEX_PPPMINLEN)
2588 goto drop;
2589
2590 return (m0);
2591 drop:
2592 m_freem(m0);
2593 return (NULL);
2594 }
2595
2596 struct mbuf *
pipex_mppe_output(struct mbuf * m0,struct pipex_session * session,uint16_t protocol)2597 pipex_mppe_output(struct mbuf *m0, struct pipex_session *session,
2598 uint16_t protocol)
2599 {
2600 int encrypt, flushed, len;
2601 struct mppe_header {
2602 uint16_t coher_cnt;
2603 uint16_t protocol;
2604 } __packed *hdr;
2605 u_char *cp;
2606 struct pipex_mppe *mppe;
2607 struct mbuf *m;
2608
2609 mppe = &session->mppe_send;
2610
2611 /*
2612 * create a deep-copy if the mbuf has a shared mbuf cluster.
2613 * this is required to handle cases of tcp retransmission.
2614 */
2615 for (m = m0; m != NULL; m = m->m_next) {
2616 if (M_READONLY(m)) {
2617 m = m_dup_pkt(m0, max_linkhdr, M_NOWAIT);
2618 m_freem(m0);
2619 if (m == NULL)
2620 return (NULL);
2621 m0 = m;
2622 break;
2623 }
2624 }
2625 /* prepend mppe header */
2626 M_PREPEND(m0, sizeof(struct mppe_header), M_NOWAIT);
2627 if (m0 == NULL)
2628 return (NULL);
2629 hdr = mtod(m0, struct mppe_header *);
2630 hdr->protocol = protocol;
2631
2632 /* check coherency counter */
2633 flushed = 0;
2634 encrypt = 1;
2635
2636 mtx_enter(&mppe->pxm_mtx);
2637
2638 if ((mppe->flags & PIPEX_MPPE_STATELESS) != 0) {
2639 flushed = 1;
2640 mppe_key_change(mppe);
2641 } else {
2642 if ((mppe->coher_cnt % 0x100) == 0xff) {
2643 flushed = 1;
2644 mppe_key_change(mppe);
2645 } else if ((mppe->flags & PIPEX_MPPE_RESETREQ) != 0) {
2646 flushed = 1;
2647 mppe->flags &= ~PIPEX_MPPE_RESETREQ;
2648 }
2649 }
2650
2651 if (flushed)
2652 pipex_mppe_setkey(mppe);
2653
2654 PIPEX_MPPE_DBG((session, LOG_DEBUG, "out coher_cnt=%03x %s%s",
2655 mppe->coher_cnt, (flushed) ? "[flushed]" : "",
2656 (encrypt) ? "[encrypt]" : ""));
2657
2658 /* setup header information */
2659 hdr->coher_cnt = (mppe->coher_cnt++) & PIPEX_COHERENCY_CNT_MASK;
2660 hdr->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
2661 if (flushed)
2662 hdr->coher_cnt |= 0x8000;
2663 if (encrypt)
2664 hdr->coher_cnt |= 0x1000;
2665
2666 hdr->protocol = htons(hdr->protocol);
2667 hdr->coher_cnt = htons(hdr->coher_cnt);
2668
2669 /* encrypt chain */
2670 for (m = m0; m; m = m->m_next) {
2671 cp = mtod(m, u_char *);
2672 len = m->m_len;
2673 if (m == m0 && len > offsetof(struct mppe_header, protocol)) {
2674 len -= offsetof(struct mppe_header, protocol);
2675 cp += offsetof(struct mppe_header, protocol);
2676 }
2677 pipex_mppe_crypt(mppe, len, cp, cp);
2678 }
2679
2680 mtx_leave(&mppe->pxm_mtx);
2681
2682 return (m0);
2683 }
2684
2685 void
pipex_ccp_input(struct mbuf * m0,struct pipex_session * session)2686 pipex_ccp_input(struct mbuf *m0, struct pipex_session *session)
2687 {
2688 u_char *cp;
2689 int code, id, len;
2690
2691 if (m0->m_pkthdr.len < PPP_HDRLEN)
2692 goto drop;
2693 if ((m0 = m_pullup(m0, PPP_HDRLEN)) == NULL)
2694 goto drop;
2695
2696 cp = mtod(m0, u_char *);
2697 GETCHAR(code, cp);
2698 GETCHAR(id, cp);
2699 GETSHORT(len, cp);
2700
2701 switch (code) {
2702 case CCP_RESETREQ:
2703 PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetReq"));
2704 mtx_enter(&session->mppe_send.pxm_mtx);
2705 session->mppe_send.flags |= PIPEX_MPPE_RESETREQ;
2706 mtx_leave(&session->mppe_send.pxm_mtx);
2707 #ifndef PIPEX_NO_CCP_RESETACK
2708 PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetAck"));
2709 pipex_ccp_output(session, CCP_RESETACK, id);
2710 #endif
2711 /* ignore error */
2712 break;
2713 case CCP_RESETACK:
2714 PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetAck"));
2715 break;
2716 default:
2717 PIPEX_DBG((session, LOG_DEBUG, "CCP Recv code=%d", code));
2718 goto drop;
2719 }
2720 m_freem(m0);
2721
2722 return;
2723 drop:
2724 m_freem(m0);
2725 counters_inc(session->stat_counters, pxc_ierrors);
2726 }
2727
2728 int
pipex_ccp_output(struct pipex_session * session,int code,int id)2729 pipex_ccp_output(struct pipex_session *session, int code, int id)
2730 {
2731 u_char *cp;
2732 struct mbuf *m;
2733
2734 MGETHDR(m, M_DONTWAIT, MT_DATA);
2735 if (m == NULL) {
2736 counters_inc(session->stat_counters, pxc_oerrors);
2737 return (1);
2738 }
2739 m->m_pkthdr.len = m->m_len = 4;
2740 cp = mtod(m, u_char *);
2741 PUTCHAR(code, cp);
2742 PUTCHAR(id, cp);
2743 PUTSHORT(4, cp);
2744
2745 pipex_ppp_output(m, session, PPP_CCP);
2746
2747 return (0);
2748 }
2749 #endif
2750 /***********************************************************************
2751 * Miscellaneous functions
2752 ***********************************************************************/
2753 /* adapted from FreeBSD:src/usr.sbin/ppp/tcpmss.c */
2754 /*
2755 * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org>
2756 * All rights reserved.
2757 *
2758 * Redistribution and use in source and binary forms, with or without
2759 * modification, are permitted provided that the following conditions
2760 * are met:
2761 * 1. Redistributions of source code must retain the above copyright
2762 * notice, this list of conditions and the following disclaimer.
2763 * 2. Redistributions in binary form must reproduce the above copyright
2764 * notice, this list of conditions and the following disclaimer in the
2765 * documentation and/or other materials provided with the distribution.
2766 *
2767 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2768 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2769 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2770 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2771 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2772 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2773 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2774 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2775 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2776 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2777 * SUCH DAMAGE.
2778 *
2779 * $FreeBSD: src/usr.sbin/ppp/tcpmss.c,v 1.1.4.3 2001/07/19 11:39:54 brian Exp $
2780 */
2781 #define TCP_OPTLEN_IN_SEGMENT 12 /* timestamp option and padding */
2782 #define MAXMSS(mtu) (mtu - sizeof(struct ip) - sizeof(struct tcphdr) - \
2783 TCP_OPTLEN_IN_SEGMENT)
2784 /*
2785 * The following macro is used to update an internet checksum. "acc" is a
2786 * 32-bit accumulation of all the changes to the checksum (adding in old
2787 * 16-bit words and subtracting out new words), and "cksum" is the checksum
2788 * value to be updated.
2789 */
2790 #define ADJUST_CHECKSUM(acc, cksum) { \
2791 acc += cksum; \
2792 if (acc < 0) { \
2793 acc = -acc; \
2794 acc = (acc >> 16) + (acc & 0xffff); \
2795 acc += acc >> 16; \
2796 cksum = (u_short) ~acc; \
2797 } else { \
2798 acc = (acc >> 16) + (acc & 0xffff); \
2799 acc += acc >> 16; \
2800 cksum = (u_short) acc; \
2801 } \
2802 }
2803
2804 /*
2805 * Rewrite max-segment-size TCP option to avoid PMTU blackhole issues.
2806 * The mtu parameter should be the MTU bottleneck (as far as we know)
2807 * on the link between the source and the destination.
2808 */
2809 struct mbuf *
adjust_tcp_mss(struct mbuf * m0,int mtu)2810 adjust_tcp_mss(struct mbuf *m0, int mtu)
2811 {
2812 int opt, optlen, acc, mss, maxmss, lpktp;
2813 struct ip *pip;
2814 struct tcphdr *th;
2815 u_char *pktp, *mssp;
2816 u_int16_t ip_off;
2817
2818 lpktp = sizeof(struct ip) + sizeof(struct tcphdr) + PIPEX_TCP_OPTLEN;
2819 lpktp = MIN(lpktp, m0->m_pkthdr.len);
2820
2821 PIPEX_PULLUP(m0, lpktp);
2822 if (m0 == NULL)
2823 goto drop;
2824
2825 pktp = mtod(m0, char *);
2826 pip = (struct ip *)pktp;
2827 ip_off = ntohs(pip->ip_off);
2828
2829 /* Non TCP or fragmented packet must not have a MSS option */
2830 if (pip->ip_p != IPPROTO_TCP ||
2831 (ip_off & IP_MF) != 0 || (ip_off & IP_OFFMASK) != 0)
2832 goto handled;
2833
2834 pktp += pip->ip_hl << 2;
2835 lpktp -= pip->ip_hl << 2;
2836
2837 /* packet is broken */
2838 if (sizeof(struct tcphdr) > lpktp)
2839 goto drop;
2840 th = (struct tcphdr *)pktp;
2841
2842 /*
2843 * As RFC 973, a MSS field must only be sent in the initial
2844 * connection request(it must be with SYN).
2845 */
2846 if ((th->th_flags & TH_SYN) == 0)
2847 goto handled;
2848
2849 lpktp = MIN(th->th_off << 4, lpktp);
2850
2851 pktp += sizeof(struct tcphdr);
2852 lpktp -= sizeof(struct tcphdr);
2853 while (lpktp >= TCPOLEN_MAXSEG) {
2854 GETCHAR(opt, pktp);
2855 switch (opt) {
2856 case TCPOPT_MAXSEG:
2857 GETCHAR(optlen, pktp);
2858 mssp = pktp; /* mss place holder */
2859 GETSHORT(mss, pktp);
2860 maxmss = MAXMSS(mtu);
2861 if (mss > maxmss) {
2862 PIPEX_DBG((NULL, LOG_DEBUG,
2863 "change tcp-mss %d => %d", mss, maxmss));
2864 PUTSHORT(maxmss, mssp);
2865 acc = htons(mss);
2866 acc -= htons(maxmss);
2867 ADJUST_CHECKSUM(acc, th->th_sum);
2868 }
2869 goto handled;
2870 /* NOTREACHED */
2871 case TCPOPT_EOL:
2872 goto handled;
2873 /* NOTREACHED */
2874 case TCPOPT_NOP:
2875 lpktp--;
2876 break;
2877 default:
2878 GETCHAR(optlen, pktp);
2879 if (optlen < 2) /* packet is broken */
2880 goto drop;
2881 pktp += optlen - 2;
2882 lpktp -= optlen;
2883 break;
2884 }
2885 }
2886
2887 handled:
2888 return (m0);
2889
2890 drop:
2891 m_freem(m0);
2892 return (NULL);
2893 }
2894
2895 /*
2896 * Check whether a packet should reset idle timer
2897 * Returns 1 to don't reset timer (i.e. the packet is "idle" packet)
2898 */
2899 struct mbuf *
ip_is_idle_packet(struct mbuf * m0,int * ris_idle)2900 ip_is_idle_packet(struct mbuf *m0, int *ris_idle)
2901 {
2902 u_int16_t ip_off;
2903 const struct udphdr *uh;
2904 struct ip *pip;
2905 int len;
2906
2907 /* pullup ip header */
2908 len = sizeof(struct ip);
2909 PIPEX_PULLUP(m0, len);
2910 if (m0 == NULL)
2911 goto error;
2912 pip = mtod(m0, struct ip *);
2913
2914 /*
2915 * the packet which fragmentations was not the idle packet.
2916 */
2917 ip_off = ntohs(pip->ip_off);
2918 if ((ip_off & IP_MF) || ((ip_off & IP_OFFMASK) != 0))
2919 goto is_active;
2920
2921 switch (pip->ip_p) {
2922 case IPPROTO_IGMP:
2923 goto is_active;
2924 case IPPROTO_ICMP:
2925 len = pip->ip_hl * 4 + 8;
2926 PIPEX_PULLUP(m0, len);
2927 if (m0 == NULL)
2928 goto error;
2929 pip = mtod(m0, struct ip *);
2930
2931 switch (((unsigned char *) pip)[pip->ip_hl * 4]) {
2932 case 0: /* Echo Reply */
2933 case 8: /* Echo Request */
2934 goto is_active;
2935 default:
2936 goto is_idle;
2937 }
2938
2939 case IPPROTO_UDP:
2940 case IPPROTO_TCP:
2941 len = pip->ip_hl * 4 + sizeof(struct udphdr);
2942 PIPEX_PULLUP(m0, len);
2943 if (m0 == NULL)
2944 goto error;
2945 pip = mtod(m0, struct ip *);
2946 uh = (struct udphdr *)(mtod(m0, caddr_t) + pip->ip_hl * 4);
2947
2948 switch (ntohs(uh->uh_sport)) {
2949 case 53: /* DOMAIN */
2950 case 67: /* BOOTPS */
2951 case 68: /* BOOTPC */
2952 case 123: /* NTP */
2953 case 137: /* NETBIOS-NS */
2954 case 520: /* RIP */
2955 goto is_idle;
2956 }
2957 switch (ntohs(uh->uh_dport)) {
2958 case 53: /* DOMAIN */
2959 case 67: /* BOOTPS */
2960 case 68: /* BOOTPC */
2961 case 123: /* NTP */
2962 case 137: /* NETBIOS-NS */
2963 case 520: /* RIP */
2964 goto is_idle;
2965 }
2966 goto is_active;
2967 default:
2968 goto is_active;
2969 }
2970
2971 is_active:
2972 *ris_idle = 0;
2973 return (m0);
2974
2975 is_idle:
2976 *ris_idle = 1;
2977 return (m0);
2978
2979 error:
2980 return (NULL);
2981 }
2982
2983 void
pipex_session_log(struct pipex_session * session,int prio,const char * fmt,...)2984 pipex_session_log(struct pipex_session *session, int prio, const char *fmt, ...)
2985 {
2986 char logbuf[1024];
2987 va_list ap;
2988
2989 logpri(prio);
2990 if (session != NULL) {
2991 struct ifnet *ifp;
2992
2993 ifp = if_get(session->ifindex);
2994 addlog("pipex: ppp=%d iface=%s protocol=%s id=%d ",
2995 session->ppp_id,
2996 ifp? ifp->if_xname : "Unknown",
2997 (session->protocol == PIPEX_PROTO_PPPOE)? "PPPoE" :
2998 (session->protocol == PIPEX_PROTO_PPTP)? "PPTP" :
2999 (session->protocol == PIPEX_PROTO_L2TP) ? "L2TP" :
3000 "Unknown", session->session_id);
3001 if_put(ifp);
3002 } else
3003 addlog("pipex: ");
3004
3005 va_start(ap, fmt);
3006 vsnprintf(logbuf, sizeof(logbuf), fmt, ap);
3007 va_end(ap);
3008 addlog("%s\n", logbuf);
3009 }
3010
3011 uint32_t
pipex_sockaddr_hash_key(struct sockaddr * sa)3012 pipex_sockaddr_hash_key(struct sockaddr *sa)
3013 {
3014 switch (sa->sa_family) {
3015 case AF_INET:
3016 return ntohl(satosin(sa)->sin_addr.s_addr);
3017 case AF_INET6:
3018 return ntohl(satosin6(sa)->sin6_addr.s6_addr32[3]);
3019 }
3020 panic("pipex_sockaddr_hash_key: unknown address family");
3021 return (0);
3022 }
3023
3024 /*
3025 * Compare struct sockaddr_in{,6} with the address only.
3026 * The port number is not covered.
3027 */
3028 int
pipex_sockaddr_compar_addr(struct sockaddr * a,struct sockaddr * b)3029 pipex_sockaddr_compar_addr(struct sockaddr *a, struct sockaddr *b)
3030 {
3031 int cmp;
3032
3033 cmp = b->sa_family - a->sa_family;
3034 if (cmp != 0)
3035 return cmp;
3036 switch (a->sa_family) {
3037 case AF_INET:
3038 return (satosin(b)->sin_addr.s_addr -
3039 satosin(a)->sin_addr.s_addr);
3040 case AF_INET6:
3041 cmp = (satosin6(b)->sin6_scope_id - satosin6(a)->sin6_scope_id);
3042 if (cmp != 0)
3043 return cmp;
3044 return (memcmp(&satosin6(a)->sin6_addr,
3045 &satosin6(b)->sin6_addr,
3046 sizeof(struct in6_addr)));
3047 }
3048 panic("pipex_sockaddr_compar_addr: unknown address family");
3049
3050 return (-1);
3051 }
3052
3053 int
pipex_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)3054 pipex_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
3055 size_t newlen)
3056 {
3057 switch (name[0]) {
3058 case PIPEXCTL_ENABLE:
3059 if (namelen != 1)
3060 return (ENOTDIR);
3061 return (sysctl_int_bounded(oldp, oldlenp, newp, newlen,
3062 &pipex_enable, 0, 1));
3063 default:
3064 return (ENOPROTOOPT);
3065 }
3066 /* NOTREACHED */
3067 }
3068