FreeBSD/Linux Kernel Cross Reference
sys/net/if_ppp.c
1 /* $OpenBSD: if_ppp.c,v 1.117 2020/08/21 22:59:27 kn Exp $ */
2 /* $NetBSD: if_ppp.c,v 1.39 1997/05/17 21:11:59 christos Exp $ */
3
4 /*
5 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
6 *
7 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The name "Carnegie Mellon University" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For permission or any legal
24 * details, please contact
25 * Office of Technology Transfer
26 * Carnegie Mellon University
27 * 5000 Forbes Avenue
28 * Pittsburgh, PA 15213-3890
29 * (412) 268-4387, fax: (412) 268-7395
30 * tech-transfer@andrew.cmu.edu
31 *
32 * 4. Redistributions of any form whatsoever must retain the following
33 * acknowledgment:
34 * "This product includes software developed by Computing Services
35 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
36 *
37 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
38 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
40 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
42 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
43 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 *
45 * Based on:
46 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
47 *
48 * Copyright (c) 1987, 1989, 1992, 1993
49 * The Regents of the University of California. All rights reserved.
50 *
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 * 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 * notice, this list of conditions and the following disclaimer in the
58 * documentation and/or other materials provided with the distribution.
59 * 3. Neither the name of the University nor the names of its contributors
60 * may be used to endorse or promote products derived from this software
61 * without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * SUCH DAMAGE.
74 *
75 * Serial Line interface
76 *
77 * Rick Adams
78 * Center for Seismic Studies
79 * 1300 N 17th Street, Suite 1450
80 * Arlington, Virginia 22209
81 * (703)276-7900
82 * rick@seismo.ARPA
83 * seismo!rick
84 *
85 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
86 * Converted to 4.3BSD Beta by Chris Torek.
87 * Other changes made at Berkeley, based in part on code by Kirk Smith.
88 *
89 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
90 * Added VJ tcp header compression; more unified ioctls
91 *
92 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
93 * Cleaned up a lot of the mbuf-related code to fix bugs that
94 * caused system crashes and packet corruption. Changed pppstart
95 * so that it doesn't just give up with a collision if the whole
96 * packet doesn't fit in the output ring buffer.
97 *
98 * Added priority queueing for interactive IP packets, following
99 * the model of if_sl.c, plus hooks for bpf.
100 * Paul Mackerras (paulus@cs.anu.edu.au).
101 */
102
103 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
104 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
105
106 #include "ppp.h"
107 #if NPPP > 0
108
109 #define VJC
110 #define PPP_COMPRESS
111
112 #include <sys/param.h>
113 #include <sys/proc.h>
114 #include <sys/mbuf.h>
115 #include <sys/socket.h>
116 #include <sys/ioctl.h>
117 #include <sys/kernel.h>
118 #include <sys/systm.h>
119 #include <sys/time.h>
120 #include <sys/malloc.h>
121
122 #include <net/if.h>
123 #include <net/if_var.h>
124 #include <net/if_types.h>
125 #include <net/netisr.h>
126 #include <net/route.h>
127 #include <net/bpf.h>
128
129 #include <netinet/in.h>
130 #include <netinet/ip.h>
131
132 #include "bpfilter.h"
133
134 #ifdef VJC
135 #include <net/slcompress.h>
136 #endif
137
138 #include <net/ppp_defs.h>
139 #include <net/if_ppp.h>
140 #include <net/if_pppvar.h>
141
142 #ifdef PPP_COMPRESS
143 #define PACKETPTR struct mbuf *
144 #include <net/ppp-comp.h>
145 #endif
146
147 static int pppsioctl(struct ifnet *, u_long, caddr_t);
148 static void ppp_requeue(struct ppp_softc *);
149 static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd);
150 static void ppp_ccp_closed(struct ppp_softc *);
151 static void ppp_inproc(struct ppp_softc *, struct mbuf *);
152 static void pppdumpm(struct mbuf *m0);
153 static void ppp_ifstart(struct ifnet *ifp);
154 int ppp_clone_create(struct if_clone *, int);
155 int ppp_clone_destroy(struct ifnet *);
156
157 void ppp_pkt_list_init(struct ppp_pkt_list *, u_int);
158 int ppp_pkt_enqueue(struct ppp_pkt_list *, struct ppp_pkt *);
159 struct ppp_pkt *ppp_pkt_dequeue(struct ppp_pkt_list *);
160 struct mbuf *ppp_pkt_mbuf(struct ppp_pkt *);
161
162 /*
163 * We steal two bits in the mbuf m_flags, to mark high-priority packets
164 * for output, and received packets following lost/corrupted packets.
165 */
166 #define M_ERRMARK M_LINK0 /* steal a bit in mbuf m_flags */
167
168
169 #ifdef PPP_COMPRESS
170 /*
171 * List of compressors we know about.
172 */
173
174 extern struct compressor ppp_bsd_compress;
175 extern struct compressor ppp_deflate, ppp_deflate_draft;
176
177 struct compressor *ppp_compressors[] = {
178 #if DO_BSD_COMPRESS && defined(PPP_BSDCOMP)
179 &ppp_bsd_compress,
180 #endif
181 #if DO_DEFLATE && defined(PPP_DEFLATE)
182 &ppp_deflate,
183 &ppp_deflate_draft,
184 #endif
185 NULL
186 };
187 #endif /* PPP_COMPRESS */
188
189 LIST_HEAD(, ppp_softc) ppp_softc_list;
190 struct if_clone ppp_cloner =
191 IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy);
192
193 /*
194 * Called from boot code to establish ppp interfaces.
195 */
196 void
197 pppattach(void)
198 {
199 LIST_INIT(&ppp_softc_list);
200 if_clone_attach(&ppp_cloner);
201 }
202
203 int
204 ppp_clone_create(struct if_clone *ifc, int unit)
205 {
206 struct ppp_softc *sc;
207 struct ifnet *ifp;
208
209 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
210 sc->sc_unit = unit;
211 ifp = &sc->sc_if;
212 snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d",
213 ifc->ifc_name, unit);
214 sc->sc_if.if_softc = sc;
215 sc->sc_if.if_mtu = PPP_MTU;
216 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
217 sc->sc_if.if_type = IFT_PPP;
218 sc->sc_if.if_hdrlen = PPP_HDRLEN;
219 sc->sc_if.if_ioctl = pppsioctl;
220 sc->sc_if.if_output = pppoutput;
221 sc->sc_if.if_start = ppp_ifstart;
222 sc->sc_if.if_rtrequest = p2p_rtrequest;
223 mq_init(&sc->sc_inq, IFQ_MAXLEN, IPL_NET);
224 ppp_pkt_list_init(&sc->sc_rawq, IFQ_MAXLEN);
225 if_attach(&sc->sc_if);
226 if_alloc_sadl(&sc->sc_if);
227 #if NBPFILTER > 0
228 bpfattach(&ifp->if_bpf, ifp, DLT_PPP, PPP_HDRLEN);
229 #endif
230 NET_LOCK();
231 LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_list);
232 NET_UNLOCK();
233
234 return (0);
235 }
236
237 int
238 ppp_clone_destroy(struct ifnet *ifp)
239 {
240 struct ppp_softc *sc = ifp->if_softc;
241
242 if (sc->sc_devp != NULL)
243 return (EBUSY);
244
245 NET_LOCK();
246 LIST_REMOVE(sc, sc_list);
247 NET_UNLOCK();
248
249 if_detach(ifp);
250
251 free(sc, M_DEVBUF, 0);
252 return (0);
253 }
254
255 /*
256 * Allocate a ppp interface unit and initialize it.
257 */
258 struct ppp_softc *
259 pppalloc(pid_t pid)
260 {
261 int i;
262 struct ppp_softc *sc;
263
264 NET_LOCK();
265 LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
266 if (sc->sc_xfer == pid) {
267 sc->sc_xfer = 0;
268 NET_UNLOCK();
269 return sc;
270 }
271 }
272 LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
273 if (sc->sc_devp == NULL)
274 break;
275 }
276 NET_UNLOCK();
277 if (sc == NULL)
278 return NULL;
279
280 sc->sc_flags = 0;
281 sc->sc_mru = PPP_MRU;
282 sc->sc_relinq = NULL;
283 bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
284 #ifdef VJC
285 sc->sc_comp = malloc(sizeof(struct slcompress), M_DEVBUF, M_NOWAIT);
286 if (sc->sc_comp)
287 sl_compress_init(sc->sc_comp);
288 #endif
289 #ifdef PPP_COMPRESS
290 sc->sc_xc_state = NULL;
291 sc->sc_rc_state = NULL;
292 #endif /* PPP_COMPRESS */
293 for (i = 0; i < NUM_NP; ++i)
294 sc->sc_npmode[i] = NPMODE_ERROR;
295 ml_init(&sc->sc_npqueue);
296 sc->sc_last_sent = sc->sc_last_recv = getuptime();
297
298 return sc;
299 }
300
301 /*
302 * Deallocate a ppp unit.
303 */
304 void
305 pppdealloc(struct ppp_softc *sc)
306 {
307 struct ppp_pkt *pkt;
308
309 NET_LOCK();
310 if_down(&sc->sc_if);
311 sc->sc_if.if_flags &= ~IFF_RUNNING;
312 sc->sc_devp = NULL;
313 sc->sc_xfer = 0;
314 while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL)
315 ppp_pkt_free(pkt);
316 mq_purge(&sc->sc_inq);
317 ml_purge(&sc->sc_npqueue);
318 m_freem(sc->sc_togo);
319 sc->sc_togo = NULL;
320
321 #ifdef PPP_COMPRESS
322 ppp_ccp_closed(sc);
323 sc->sc_xc_state = NULL;
324 sc->sc_rc_state = NULL;
325 #endif /* PPP_COMPRESS */
326 #if NBPFILTER > 0
327 if (sc->sc_pass_filt.bf_insns != 0) {
328 free(sc->sc_pass_filt.bf_insns, M_DEVBUF, 0);
329 sc->sc_pass_filt.bf_insns = 0;
330 sc->sc_pass_filt.bf_len = 0;
331 }
332 if (sc->sc_active_filt.bf_insns != 0) {
333 free(sc->sc_active_filt.bf_insns, M_DEVBUF, 0);
334 sc->sc_active_filt.bf_insns = 0;
335 sc->sc_active_filt.bf_len = 0;
336 }
337 #endif
338 #ifdef VJC
339 if (sc->sc_comp != 0) {
340 free(sc->sc_comp, M_DEVBUF, 0);
341 sc->sc_comp = 0;
342 }
343 #endif
344 NET_UNLOCK();
345 }
346
347 /*
348 * Ioctl routine for generic ppp devices.
349 */
350 int
351 pppioctl(struct ppp_softc *sc, u_long cmd, caddr_t data, int flag,
352 struct proc *p)
353 {
354 int s, error, flags, mru, npx;
355 u_int nb;
356 struct ppp_option_data *odp;
357 struct compressor **cp;
358 struct npioctl *npi;
359 time_t t;
360 #if NBPFILTER > 0
361 struct bpf_program *bp, *nbp;
362 struct bpf_insn *newcode, *oldcode;
363 int newcodelen;
364 #endif
365 #ifdef PPP_COMPRESS
366 u_char ccp_option[CCP_MAX_OPTION_LENGTH];
367 #endif
368
369 switch (cmd) {
370 case FIONREAD:
371 *(int *)data = mq_len(&sc->sc_inq);
372 break;
373
374 case PPPIOCGUNIT:
375 *(int *)data = sc->sc_unit; /* XXX */
376 break;
377
378 case PPPIOCGFLAGS:
379 *(u_int *)data = sc->sc_flags;
380 break;
381
382 case PPPIOCSFLAGS:
383 if ((error = suser(p)) != 0)
384 return (error);
385 flags = *(int *)data & SC_MASK;
386 #ifdef PPP_COMPRESS
387 if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
388 ppp_ccp_closed(sc);
389 #endif
390 s = splnet();
391 sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
392 splx(s);
393 break;
394
395 case PPPIOCSMRU:
396 if ((error = suser(p)) != 0)
397 return (error);
398 mru = *(int *)data;
399 if (mru >= PPP_MRU && mru <= PPP_MAXMRU)
400 sc->sc_mru = mru;
401 break;
402
403 case PPPIOCGMRU:
404 *(int *)data = sc->sc_mru;
405 break;
406
407 #ifdef VJC
408 case PPPIOCSMAXCID:
409 if ((error = suser(p)) != 0)
410 return (error);
411 if (sc->sc_comp)
412 sl_compress_setup(sc->sc_comp, *(int *)data);
413 break;
414 #endif
415
416 case PPPIOCXFERUNIT:
417 if ((error = suser(p)) != 0)
418 return (error);
419 sc->sc_xfer = p->p_p->ps_pid;
420 break;
421
422 #ifdef PPP_COMPRESS
423 case PPPIOCSCOMPRESS:
424 if ((error = suser(p)) != 0)
425 return (error);
426 odp = (struct ppp_option_data *) data;
427 nb = odp->length;
428 if (nb > sizeof(ccp_option))
429 nb = sizeof(ccp_option);
430 if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
431 return (error);
432 /* preliminary check on the length byte */
433 if (ccp_option[1] < 2)
434 return (EINVAL);
435 for (cp = ppp_compressors; *cp != NULL; ++cp)
436 if ((*cp)->compress_proto == ccp_option[0]) {
437 /*
438 * Found a handler for the protocol - try to allocate
439 * a compressor or decompressor.
440 */
441 error = 0;
442 if (odp->transmit) {
443 if (sc->sc_xc_state != NULL) {
444 (*sc->sc_xcomp->comp_free)(
445 sc->sc_xc_state);
446 }
447 sc->sc_xcomp = *cp;
448 sc->sc_xc_state = (*cp)->comp_alloc(ccp_option,
449 nb);
450 if (sc->sc_xc_state == NULL) {
451 if (sc->sc_flags & SC_DEBUG)
452 printf(
453 "%s: comp_alloc failed\n",
454 sc->sc_if.if_xname);
455 error = ENOBUFS;
456 }
457 s = splnet();
458 sc->sc_flags &= ~SC_COMP_RUN;
459 splx(s);
460 } else {
461 if (sc->sc_rc_state != NULL) {
462 (*sc->sc_rcomp->decomp_free)(
463 sc->sc_rc_state);
464 }
465 sc->sc_rcomp = *cp;
466 sc->sc_rc_state = (*cp)->decomp_alloc(
467 ccp_option, nb);
468 if (sc->sc_rc_state == NULL) {
469 if (sc->sc_flags & SC_DEBUG) {
470 printf(
471 "%s: decomp_alloc failed\n",
472 sc->sc_if.if_xname);
473 }
474 error = ENOBUFS;
475 }
476 s = splnet();
477 sc->sc_flags &= ~SC_DECOMP_RUN;
478 splx(s);
479 }
480 return (error);
481 }
482 if (sc->sc_flags & SC_DEBUG) {
483 printf("%s: no compressor for [%x %x %x], %x\n",
484 sc->sc_if.if_xname, ccp_option[0], ccp_option[1],
485 ccp_option[2], nb);
486 }
487 return (EINVAL); /* no handler found */
488 #endif /* PPP_COMPRESS */
489
490 case PPPIOCGNPMODE:
491 case PPPIOCSNPMODE:
492 npi = (struct npioctl *)data;
493 switch (npi->protocol) {
494 case PPP_IP:
495 npx = NP_IP;
496 break;
497 default:
498 return EINVAL;
499 }
500 if (cmd == PPPIOCGNPMODE) {
501 npi->mode = sc->sc_npmode[npx];
502 } else {
503 if ((error = suser(p)) != 0)
504 return (error);
505 if (npi->mode != sc->sc_npmode[npx]) {
506 sc->sc_npmode[npx] = npi->mode;
507 if (npi->mode != NPMODE_QUEUE) {
508 ppp_requeue(sc);
509 (*sc->sc_start)(sc);
510 }
511 }
512 }
513 break;
514
515 case PPPIOCGIDLE:
516 t = getuptime();
517 ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
518 ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
519 break;
520
521 #if NBPFILTER > 0
522 case PPPIOCSPASS:
523 case PPPIOCSACTIVE:
524 nbp = (struct bpf_program *) data;
525 if ((unsigned) nbp->bf_len > BPF_MAXINSNS)
526 return EINVAL;
527 newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
528 if (nbp->bf_len != 0) {
529 newcode = mallocarray(nbp->bf_len,
530 sizeof(struct bpf_insn), M_DEVBUF, M_WAITOK);
531 if ((error = copyin((caddr_t)nbp->bf_insns,
532 (caddr_t)newcode, newcodelen)) != 0) {
533 free(newcode, M_DEVBUF, 0);
534 return error;
535 }
536 if (!bpf_validate(newcode, nbp->bf_len)) {
537 free(newcode, M_DEVBUF, 0);
538 return EINVAL;
539 }
540 } else
541 newcode = 0;
542 bp = (cmd == PPPIOCSPASS) ?
543 &sc->sc_pass_filt : &sc->sc_active_filt;
544 oldcode = bp->bf_insns;
545 s = splnet();
546 bp->bf_len = nbp->bf_len;
547 bp->bf_insns = newcode;
548 splx(s);
549 if (oldcode != 0)
550 free(oldcode, M_DEVBUF, 0);
551 break;
552 #endif
553
554 default:
555 return (-1);
556 }
557 return (0);
558 }
559
560 /*
561 * Process an ioctl request to the ppp network interface.
562 */
563 static int
564 pppsioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
565 {
566 struct ppp_softc *sc = ifp->if_softc;
567 struct ifaddr *ifa = (struct ifaddr *)data;
568 struct ifreq *ifr = (struct ifreq *)data;
569 struct ppp_stats *psp;
570 #ifdef PPP_COMPRESS
571 struct ppp_comp_stats *pcp;
572 #endif
573 int s = splnet(), error = 0;
574
575 switch (cmd) {
576 case SIOCSIFFLAGS:
577 if ((ifp->if_flags & IFF_RUNNING) == 0)
578 ifp->if_flags &= ~IFF_UP;
579 break;
580
581 case SIOCSIFADDR:
582 if (ifa->ifa_addr->sa_family != AF_INET)
583 error = EAFNOSUPPORT;
584 break;
585
586 case SIOCSIFDSTADDR:
587 if (ifa->ifa_addr->sa_family != AF_INET)
588 error = EAFNOSUPPORT;
589 break;
590
591 case SIOCSIFMTU:
592 sc->sc_if.if_mtu = ifr->ifr_mtu;
593 break;
594
595 case SIOCADDMULTI:
596 case SIOCDELMULTI:
597 break;
598
599 case SIOCGPPPSTATS:
600 psp = &((struct ifpppstatsreq *) data)->stats;
601 bzero(psp, sizeof(*psp));
602 psp->p = sc->sc_stats;
603 #if defined(VJC) && !defined(SL_NO_STATS)
604 if (sc->sc_comp) {
605 psp->vj.vjs_packets = sc->sc_comp->sls_packets;
606 psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
607 psp->vj.vjs_searches = sc->sc_comp->sls_searches;
608 psp->vj.vjs_misses = sc->sc_comp->sls_misses;
609 psp->vj.vjs_uncompressedin =
610 sc->sc_comp->sls_uncompressedin;
611 psp->vj.vjs_compressedin =
612 sc->sc_comp->sls_compressedin;
613 psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
614 psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
615 }
616 #endif /* VJC */
617 break;
618
619 #ifdef PPP_COMPRESS
620 case SIOCGPPPCSTATS:
621 pcp = &((struct ifpppcstatsreq *) data)->stats;
622 bzero(pcp, sizeof(*pcp));
623 if (sc->sc_xc_state != NULL)
624 (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
625 if (sc->sc_rc_state != NULL)
626 (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
627 break;
628 #endif /* PPP_COMPRESS */
629
630 default:
631 error = ENOTTY;
632 }
633 splx(s);
634 return (error);
635 }
636
637 /*
638 * Queue a packet. Start transmission if not active.
639 * Packet is placed in Information field of PPP frame.
640 */
641 int
642 pppoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
643 struct rtentry *rtp)
644 {
645 struct ppp_softc *sc = ifp->if_softc;
646 int protocol, address, control;
647 u_char *cp;
648 int error;
649 enum NPmode mode;
650 int len;
651
652 if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
653 || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
654 error = ENETDOWN; /* sort of */
655 goto bad;
656 }
657
658 #ifdef DIAGNOSTIC
659 if (ifp->if_rdomain != rtable_l2(m0->m_pkthdr.ph_rtableid)) {
660 printf("%s: trying to send packet on wrong domain. "
661 "if %d vs. mbuf %d, AF %d\n", ifp->if_xname,
662 ifp->if_rdomain, rtable_l2(m0->m_pkthdr.ph_rtableid),
663 dst->sa_family);
664 }
665 #endif
666
667 /*
668 * Compute PPP header.
669 */
670 switch (dst->sa_family) {
671 case AF_INET:
672 address = PPP_ALLSTATIONS;
673 control = PPP_UI;
674 protocol = PPP_IP;
675 mode = sc->sc_npmode[NP_IP];
676 break;
677 case AF_UNSPEC:
678 address = PPP_ADDRESS(dst->sa_data);
679 control = PPP_CONTROL(dst->sa_data);
680 protocol = PPP_PROTOCOL(dst->sa_data);
681 mode = NPMODE_PASS;
682 break;
683 default:
684 printf("%s: af%d not supported\n", ifp->if_xname,
685 dst->sa_family);
686 error = EAFNOSUPPORT;
687 goto bad;
688 }
689
690 /*
691 * Drop this packet, or return an error, if necessary.
692 */
693 if (mode == NPMODE_ERROR) {
694 error = ENETDOWN;
695 goto bad;
696 }
697 if (mode == NPMODE_DROP) {
698 error = 0;
699 goto bad;
700 }
701
702 /*
703 * Add PPP header. If no space in first mbuf, allocate another.
704 */
705 M_PREPEND(m0, PPP_HDRLEN, M_DONTWAIT);
706 if (m0 == NULL) {
707 error = ENOBUFS;
708 goto bad;
709 }
710
711 cp = mtod(m0, u_char *);
712 *cp++ = address;
713 *cp++ = control;
714 *cp++ = protocol >> 8;
715 *cp++ = protocol & 0xff;
716
717 if ((m0->m_flags & M_PKTHDR) == 0)
718 panic("mbuf packet without packet header!");
719 len = m0->m_pkthdr.len;
720
721 if (sc->sc_flags & SC_LOG_OUTPKT) {
722 printf("%s output: ", ifp->if_xname);
723 pppdumpm(m0);
724 }
725
726 if ((protocol & 0x8000) == 0) {
727 #if NBPFILTER > 0
728 /*
729 * Apply the pass and active filters to the packet,
730 * but only if it is a data packet.
731 */
732 *mtod(m0, u_char *) = 1; /* indicates outbound */
733 if (sc->sc_pass_filt.bf_insns != 0 &&
734 bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *)m0,
735 len, 0) == 0) {
736 error = 0; /* drop this packet */
737 goto bad;
738 }
739
740 /*
741 * Update the time we sent the most recent packet.
742 */
743 if (sc->sc_active_filt.bf_insns == 0 ||
744 bpf_filter(sc->sc_active_filt.bf_insns, (u_char *)m0,
745 len, 0))
746 sc->sc_last_sent = getuptime();
747
748 *mtod(m0, u_char *) = address;
749 #else
750 /*
751 * Update the time we sent the most recent packet.
752 */
753 sc->sc_last_sent = getuptime();
754 #endif
755 }
756
757 #if NBPFILTER > 0
758 /* See if bpf wants to look at the packet. */
759 if (ifp->if_bpf)
760 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
761 #endif
762
763 /*
764 * Put the packet on the appropriate queue.
765 */
766 if (mode == NPMODE_QUEUE) {
767 /* XXX we should limit the number of packets on this queue */
768 ml_enqueue(&sc->sc_npqueue, m0);
769 } else {
770 error = ifq_enqueue(&sc->sc_if.if_snd, m0);
771 if (error) {
772 sc->sc_if.if_oerrors++;
773 sc->sc_stats.ppp_oerrors++;
774 return (error);
775 }
776 (*sc->sc_start)(sc);
777 }
778 ifp->if_opackets++;
779 ifp->if_obytes += len;
780
781 return (0);
782
783 bad:
784 m_freem(m0);
785 return (error);
786 }
787
788
789
790 /*
791 * After a change in the NPmode for some NP, move packets from the
792 * npqueue to the send queue or the fast queue as appropriate.
793 */
794 static void
795 ppp_requeue(struct ppp_softc *sc)
796 {
797 struct mbuf_list ml = MBUF_LIST_INITIALIZER();
798 struct mbuf *m;
799 enum NPmode mode;
800 int error;
801
802 while ((m = ml_dequeue(&sc->sc_npqueue)) != NULL) {
803 switch (PPP_PROTOCOL(mtod(m, u_char *))) {
804 case PPP_IP:
805 mode = sc->sc_npmode[NP_IP];
806 break;
807 default:
808 mode = NPMODE_PASS;
809 }
810
811 switch (mode) {
812 case NPMODE_PASS:
813 error = ifq_enqueue(&sc->sc_if.if_snd, m);
814 if (error) {
815 sc->sc_if.if_oerrors++;
816 sc->sc_stats.ppp_oerrors++;
817 }
818 break;
819
820 case NPMODE_DROP:
821 case NPMODE_ERROR:
822 m_freem(m);
823 break;
824
825 case NPMODE_QUEUE:
826 ml_enqueue(&ml, m);
827 break;
828 }
829 }
830 sc->sc_npqueue = ml;
831 }
832
833 /*
834 * Transmitter has finished outputting some stuff;
835 */
836 void
837 ppp_restart(struct ppp_softc *sc)
838 {
839 int s = splnet();
840
841 sc->sc_flags &= ~SC_TBUSY;
842 schednetisr(NETISR_PPP);
843 splx(s);
844 }
845
846 /*
847 * Get a packet to send.
848 */
849 struct mbuf *
850 ppp_dequeue(struct ppp_softc *sc)
851 {
852 struct mbuf *m, *mp;
853 u_char *cp;
854 int address, control, protocol;
855
856 /*
857 * Grab a packet to send: first try the fast queue, then the
858 * normal queue.
859 */
860 m = ifq_dequeue(&sc->sc_if.if_snd);
861 if (m == NULL)
862 return NULL;
863
864 ++sc->sc_stats.ppp_opackets;
865
866 /*
867 * Extract the ppp header of the new packet.
868 * The ppp header will be in one mbuf.
869 */
870 cp = mtod(m, u_char *);
871 address = PPP_ADDRESS(cp);
872 control = PPP_CONTROL(cp);
873 protocol = PPP_PROTOCOL(cp);
874
875 switch (protocol) {
876 case PPP_IP:
877 #ifdef VJC
878 /*
879 * If the packet is a TCP/IP packet, see if we can compress it.
880 */
881 if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
882 struct ip *ip;
883 int type;
884
885 mp = m;
886 ip = (struct ip *)(cp + PPP_HDRLEN);
887 if (mp->m_len <= PPP_HDRLEN) {
888 mp = mp->m_next;
889 if (mp == NULL)
890 break;
891 ip = mtod(mp, struct ip *);
892 }
893 /*
894 * this code assumes the IP/TCP header is in one
895 * non-shared mbuf.
896 */
897 if (ip->ip_p == IPPROTO_TCP) {
898 type = sl_compress_tcp(mp, ip, sc->sc_comp,
899 !(sc->sc_flags & SC_NO_TCP_CCID));
900 switch (type) {
901 case TYPE_UNCOMPRESSED_TCP:
902 protocol = PPP_VJC_UNCOMP;
903 break;
904 case TYPE_COMPRESSED_TCP:
905 protocol = PPP_VJC_COMP;
906 cp = mtod(m, u_char *);
907 cp[0] = address; /* header has moved */
908 cp[1] = control;
909 cp[2] = 0;
910 break;
911 }
912 /* update protocol in PPP header */
913 cp[3] = protocol;
914 }
915 }
916 #endif /* VJC */
917 break;
918
919 #ifdef PPP_COMPRESS
920 case PPP_CCP:
921 ppp_ccp(sc, m, 0);
922 break;
923 #endif /* PPP_COMPRESS */
924 }
925
926 #ifdef PPP_COMPRESS
927 if (protocol != PPP_LCP && protocol != PPP_CCP &&
928 sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
929 struct mbuf *mcomp = NULL;
930 int slen;
931
932 slen = 0;
933 for (mp = m; mp != NULL; mp = mp->m_next)
934 slen += mp->m_len;
935 (*sc->sc_xcomp->compress)(sc->sc_xc_state, &mcomp, m, slen,
936 (sc->sc_flags & SC_CCP_UP ?
937 sc->sc_if.if_mtu + PPP_HDRLEN : 0));
938 if (mcomp != NULL) {
939 if (sc->sc_flags & SC_CCP_UP) {
940 /* Send the compressed packet instead. */
941 m_freem(m);
942 m = mcomp;
943 cp = mtod(m, u_char *);
944 protocol = cp[3];
945 } else {
946 /*
947 * Can't transmit compressed packets until
948 * CCP is up.
949 */
950 m_freem(mcomp);
951 }
952 }
953 }
954 #endif /* PPP_COMPRESS */
955
956 /*
957 * Compress the address/control and protocol, if possible.
958 */
959 if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
960 control == PPP_UI && protocol != PPP_ALLSTATIONS &&
961 protocol != PPP_LCP) {
962 /* can compress address/control */
963 m->m_data += 2;
964 m->m_len -= 2;
965 }
966 if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
967 /* can compress protocol */
968 if (mtod(m, u_char *) == cp) {
969 cp[2] = cp[1]; /* move address/control up */
970 cp[1] = cp[0];
971 }
972 ++m->m_data;
973 --m->m_len;
974 }
975
976 return m;
977 }
978
979 /*
980 * Software interrupt routine.
981 */
982 void
983 pppintr(void)
984 {
985 struct ppp_softc *sc;
986 int s;
987 struct ppp_pkt *pkt;
988 struct mbuf *m;
989
990 NET_ASSERT_LOCKED();
991
992 LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
993 if (!(sc->sc_flags & SC_TBUSY) &&
994 (!ifq_empty(&sc->sc_if.if_snd))) {
995 s = splnet();
996 sc->sc_flags |= SC_TBUSY;
997 splx(s);
998 (*sc->sc_start)(sc);
999 }
1000 while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL) {
1001 m = ppp_pkt_mbuf(pkt);
1002 if (m == NULL)
1003 continue;
1004 ppp_inproc(sc, m);
1005 }
1006 }
1007 }
1008
1009 #ifdef PPP_COMPRESS
1010 /*
1011 * Handle a CCP packet. `rcvd' is 1 if the packet was received,
1012 * 0 if it is about to be transmitted.
1013 */
1014 static void
1015 ppp_ccp(struct ppp_softc *sc, struct mbuf *m, int rcvd)
1016 {
1017 u_char *dp, *ep;
1018 struct mbuf *mp;
1019 int slen, s;
1020
1021 /*
1022 * Get a pointer to the data after the PPP header.
1023 */
1024 if (m->m_len <= PPP_HDRLEN) {
1025 mp = m->m_next;
1026 if (mp == NULL)
1027 return;
1028 dp = mtod(mp, u_char *);
1029 } else {
1030 mp = m;
1031 dp = mtod(mp, u_char *) + PPP_HDRLEN;
1032 }
1033
1034 ep = mtod(mp, u_char *) + mp->m_len;
1035 if (dp + CCP_HDRLEN > ep)
1036 return;
1037 slen = CCP_LENGTH(dp);
1038 if (dp + slen > ep) {
1039 if (sc->sc_flags & SC_DEBUG) {
1040 printf("if_ppp/ccp: not enough data in mbuf"
1041 " (%p+%x > %p+%x)\n", dp, slen,
1042 mtod(mp, u_char *), mp->m_len);
1043 }
1044 return;
1045 }
1046
1047 switch (CCP_CODE(dp)) {
1048 case CCP_CONFREQ:
1049 case CCP_TERMREQ:
1050 case CCP_TERMACK:
1051 /* CCP must be going down - disable compression */
1052 if (sc->sc_flags & SC_CCP_UP) {
1053 s = splnet();
1054 sc->sc_flags &=
1055 ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
1056 splx(s);
1057 }
1058 break;
1059
1060 case CCP_CONFACK:
1061 if (sc->sc_flags & SC_CCP_OPEN &&
1062 !(sc->sc_flags & SC_CCP_UP) &&
1063 slen >= CCP_HDRLEN + CCP_OPT_MINLEN &&
1064 slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
1065 if (!rcvd) {
1066 /* we're agreeing to send compressed packets. */
1067 if (sc->sc_xc_state != NULL &&
1068 (*sc->sc_xcomp->comp_init)(sc->sc_xc_state,
1069 dp + CCP_HDRLEN, slen - CCP_HDRLEN,
1070 sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) {
1071 s = splnet();
1072 sc->sc_flags |= SC_COMP_RUN;
1073 splx(s);
1074 }
1075 } else {
1076 /* peer agrees to send compressed packets */
1077 if (sc->sc_rc_state != NULL &&
1078 (*sc->sc_rcomp->decomp_init)(
1079 sc->sc_rc_state, dp + CCP_HDRLEN,
1080 slen - CCP_HDRLEN, sc->sc_unit, 0,
1081 sc->sc_mru, sc->sc_flags & SC_DEBUG)) {
1082 s = splnet();
1083 sc->sc_flags |= SC_DECOMP_RUN;
1084 sc->sc_flags &=
1085 ~(SC_DC_ERROR | SC_DC_FERROR);
1086 splx(s);
1087 }
1088 }
1089 }
1090 break;
1091
1092 case CCP_RESETACK:
1093 if (sc->sc_flags & SC_CCP_UP) {
1094 if (!rcvd) {
1095 if (sc->sc_xc_state &&
1096 (sc->sc_flags & SC_COMP_RUN)) {
1097 (*sc->sc_xcomp->comp_reset)(
1098 sc->sc_xc_state);
1099 }
1100 } else {
1101 if (sc->sc_rc_state &&
1102 (sc->sc_flags & SC_DECOMP_RUN)) {
1103 (*sc->sc_rcomp->decomp_reset)(
1104 sc->sc_rc_state);
1105 s = splnet();
1106 sc->sc_flags &= ~SC_DC_ERROR;
1107 splx(s);
1108 }
1109 }
1110 }
1111 break;
1112 }
1113 }
1114
1115 /*
1116 * CCP is down; free (de)compressor state if necessary.
1117 */
1118 static void
1119 ppp_ccp_closed(struct ppp_softc *sc)
1120 {
1121 if (sc->sc_xc_state) {
1122 (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
1123 sc->sc_xc_state = NULL;
1124 }
1125 if (sc->sc_rc_state) {
1126 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
1127 sc->sc_rc_state = NULL;
1128 }
1129 }
1130 #endif /* PPP_COMPRESS */
1131
1132 /*
1133 * PPP packet input routine.
1134 * The caller has checked and removed the FCS and has inserted
1135 * the address/control bytes and the protocol high byte if they
1136 * were omitted.
1137 */
1138 void
1139 ppppktin(struct ppp_softc *sc, struct ppp_pkt *pkt, int lost)
1140 {
1141 pkt->p_hdr.ph_errmark = lost;
1142 if (ppp_pkt_enqueue(&sc->sc_rawq, pkt) == 0)
1143 schednetisr(NETISR_PPP);
1144 }
1145
1146 /*
1147 * Process a received PPP packet, doing decompression as necessary.
1148 */
1149 #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
1150 TYPE_UNCOMPRESSED_TCP)
1151
1152 static void
1153 ppp_inproc(struct ppp_softc *sc, struct mbuf *m)
1154 {
1155 struct ifnet *ifp = &sc->sc_if;
1156 int s, ilen, xlen, proto, rv;
1157 u_char *cp, adrs, ctrl;
1158 struct mbuf *mp, *dmp = NULL;
1159 u_char *iphdr;
1160 u_int hlen;
1161
1162 sc->sc_stats.ppp_ipackets++;
1163
1164 if (sc->sc_flags & SC_LOG_INPKT) {
1165 ilen = 0;
1166 for (mp = m; mp != NULL; mp = mp->m_next)
1167 ilen += mp->m_len;
1168 printf("%s: got %d bytes\n", ifp->if_xname, ilen);
1169 pppdumpm(m);
1170 }
1171
1172 cp = mtod(m, u_char *);
1173 adrs = PPP_ADDRESS(cp);
1174 ctrl = PPP_CONTROL(cp);
1175 proto = PPP_PROTOCOL(cp);
1176
1177 if (m->m_flags & M_ERRMARK) {
1178 m->m_flags &= ~M_ERRMARK;
1179 s = splnet();
1180 sc->sc_flags |= SC_VJ_RESET;
1181 splx(s);
1182 }
1183
1184 #ifdef PPP_COMPRESS
1185 /*
1186 * Decompress this packet if necessary, update the receiver's
1187 * dictionary, or take appropriate action on a CCP packet.
1188 */
1189 if (proto == PPP_COMP && sc->sc_rc_state &&
1190 (sc->sc_flags & SC_DECOMP_RUN) && !(sc->sc_flags & SC_DC_ERROR) &&
1191 !(sc->sc_flags & SC_DC_FERROR)) {
1192 /* decompress this packet */
1193 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
1194 if (rv == DECOMP_OK) {
1195 m_freem(m);
1196 if (dmp == NULL) {
1197 /*
1198 * no error, but no decompressed packet
1199 * produced
1200 */
1201 return;
1202 }
1203 m = dmp;
1204 cp = mtod(m, u_char *);
1205 proto = PPP_PROTOCOL(cp);
1206
1207 } else {
1208 /*
1209 * An error has occurred in decompression.
1210 * Pass the compressed packet up to pppd, which may
1211 * take CCP down or issue a Reset-Req.
1212 */
1213 if (sc->sc_flags & SC_DEBUG) {
1214 printf("%s: decompress failed %d\n",
1215 ifp->if_xname, rv);
1216 }
1217 s = splnet();
1218 sc->sc_flags |= SC_VJ_RESET;
1219 if (rv == DECOMP_ERROR)
1220 sc->sc_flags |= SC_DC_ERROR;
1221 else
1222 sc->sc_flags |= SC_DC_FERROR;
1223 splx(s);
1224 }
1225
1226 } else {
1227 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1228 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
1229 }
1230 if (proto == PPP_CCP) {
1231 ppp_ccp(sc, m, 1);
1232 }
1233 }
1234 #endif
1235
1236 ilen = 0;
1237 for (mp = m; mp != NULL; mp = mp->m_next)
1238 ilen += mp->m_len;
1239
1240 #ifdef VJC
1241 if (sc->sc_flags & SC_VJ_RESET) {
1242 /*
1243 * If we've missed a packet, we must toss subsequent compressed
1244 * packets which don't have an explicit connection ID.
1245 */
1246 if (sc->sc_comp)
1247 sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
1248 s = splnet();
1249 sc->sc_flags &= ~SC_VJ_RESET;
1250 splx(s);
1251 }
1252
1253 /*
1254 * See if we have a VJ-compressed packet to uncompress.
1255 */
1256 if (proto == PPP_VJC_COMP) {
1257 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
1258 goto bad;
1259
1260 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN,
1261 m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN,
1262 TYPE_COMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen);
1263
1264 if (xlen <= 0) {
1265 if (sc->sc_flags & SC_DEBUG) {
1266 printf("%s: VJ uncompress failed "
1267 "on type comp\n", ifp->if_xname);
1268 }
1269 goto bad;
1270 }
1271
1272 /* Copy the PPP and IP headers into a new mbuf. */
1273 MGETHDR(mp, M_DONTWAIT, MT_DATA);
1274 if (mp == NULL)
1275 goto bad;
1276 mp->m_len = 0;
1277 mp->m_next = NULL;
1278 if (hlen + PPP_HDRLEN > MHLEN) {
1279 MCLGET(mp, M_DONTWAIT);
1280 if (m_trailingspace(mp) < hlen + PPP_HDRLEN) {
1281 m_freem(mp);
1282 /* lose if big headers and no clusters */
1283 goto bad;
1284 }
1285 }
1286 if (m->m_flags & M_PKTHDR)
1287 M_MOVE_HDR(mp, m);
1288 cp = mtod(mp, u_char *);
1289 cp[0] = adrs;
1290 cp[1] = ctrl;
1291 cp[2] = 0;
1292 cp[3] = PPP_IP;
1293 proto = PPP_IP;
1294 bcopy(iphdr, cp + PPP_HDRLEN, hlen);
1295 mp->m_len = hlen + PPP_HDRLEN;
1296
1297 /*
1298 * Trim the PPP and VJ headers off the old mbuf
1299 * and stick the new and old mbufs together.
1300 */
1301 m->m_data += PPP_HDRLEN + xlen;
1302 m->m_len -= PPP_HDRLEN + xlen;
1303 if (m->m_len <= m_trailingspace(mp)) {
1304 bcopy(mtod(m, u_char *),
1305 mtod(mp, u_char *) + mp->m_len, m->m_len);
1306 mp->m_len += m->m_len;
1307 mp->m_next = m_free(m);
1308 } else
1309 mp->m_next = m;
1310 m = mp;
1311 ilen += hlen - xlen;
1312
1313 } else if (proto == PPP_VJC_UNCOMP) {
1314 if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
1315 goto bad;
1316
1317 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN,
1318 m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN,
1319 TYPE_UNCOMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen);
1320
1321 if (xlen < 0) {
1322 if (sc->sc_flags & SC_DEBUG) {
1323 printf("%s: VJ uncompress failed "
1324 "on type uncomp\n", ifp->if_xname);
1325 }
1326 goto bad;
1327 }
1328
1329 proto = PPP_IP;
1330 cp[3] = PPP_IP;
1331 }
1332 #endif /* VJC */
1333
1334 m->m_pkthdr.len = ilen;
1335 m->m_pkthdr.ph_ifidx = ifp->if_index;
1336
1337 /* mark incoming routing table */
1338 m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
1339
1340 if ((proto & 0x8000) == 0) {
1341 #if NBPFILTER > 0
1342 /*
1343 * See whether we want to pass this packet, and
1344 * if it counts as link activity.
1345 */
1346 adrs = *mtod(m, u_char *); /* save address field */
1347 *mtod(m, u_char *) = 0; /* indicate inbound */
1348 if (sc->sc_pass_filt.bf_insns != 0 &&
1349 bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m,
1350 ilen, 0) == 0) {
1351 /* drop this packet */
1352 m_freem(m);
1353 return;
1354 }
1355 if (sc->sc_active_filt.bf_insns == 0 ||
1356 bpf_filter(sc->sc_active_filt.bf_insns, (u_char *)m,
1357 ilen, 0))
1358 sc->sc_last_recv = getuptime();
1359
1360 *mtod(m, u_char *) = adrs;
1361 #else
1362 /*
1363 * Record the time that we received this packet.
1364 */
1365 sc->sc_last_recv = getuptime();
1366 #endif
1367 }
1368
1369 #if NBPFILTER > 0
1370 /* See if bpf wants to look at the packet. */
1371 if (ifp->if_bpf)
1372 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1373 #endif
1374
1375 rv = 0;
1376 switch (proto) {
1377 case PPP_IP:
1378 /*
1379 * IP packet - take off the ppp header and pass it up to IP.
1380 */
1381 if ((ifp->if_flags & IFF_UP) == 0 ||
1382 sc->sc_npmode[NP_IP] != NPMODE_PASS) {
1383 /* interface is down - drop the packet. */
1384 m_freem(m);
1385 return;
1386 }
1387 m->m_pkthdr.len -= PPP_HDRLEN;
1388 m->m_data += PPP_HDRLEN;
1389 m->m_len -= PPP_HDRLEN;
1390
1391 ipv4_input(ifp, m);
1392 rv = 1;
1393 break;
1394
1395 default:
1396 /*
1397 * Some other protocol - place on input queue for read().
1398 */
1399 if (mq_enqueue(&sc->sc_inq, m) != 0) {
1400 if_congestion();
1401 rv = 0; /* failure */
1402 } else
1403 rv = 2; /* input queue */
1404 break;
1405 }
1406
1407 if (rv == 0) {
1408 /* failure */
1409 if (sc->sc_flags & SC_DEBUG)
1410 printf("%s: input queue full\n", ifp->if_xname);
1411 ifp->if_iqdrops++;
1412 goto dropped;
1413 }
1414
1415 ifp->if_ipackets++;
1416 ifp->if_ibytes += ilen;
1417
1418 if (rv == 2)
1419 (*sc->sc_ctlp)(sc);
1420
1421 return;
1422
1423 bad:
1424 m_freem(m);
1425 dropped:
1426 sc->sc_if.if_ierrors++;
1427 sc->sc_stats.ppp_ierrors++;
1428 }
1429
1430 #define MAX_DUMP_BYTES 128
1431
1432 static void
1433 pppdumpm(struct mbuf *m0)
1434 {
1435 char buf[3*MAX_DUMP_BYTES+4];
1436 char *bp = buf;
1437 struct mbuf *m;
1438 static char digits[] = "0123456789abcdef";
1439
1440 for (m = m0; m; m = m->m_next) {
1441 int l = m->m_len;
1442 u_char *rptr = mtod(m, u_char *);
1443
1444 while (l--) {
1445 if (bp > buf + sizeof(buf) - 4)
1446 goto done;
1447
1448 /* convert byte to ascii hex */
1449 *bp++ = digits[*rptr >> 4];
1450 *bp++ = digits[*rptr++ & 0xf];
1451 }
1452
1453 if (m->m_next) {
1454 if (bp > buf + sizeof(buf) - 3)
1455 goto done;
1456 *bp++ = '|';
1457 } else
1458 *bp++ = ' ';
1459 }
1460 done:
1461 if (m)
1462 *bp++ = '>';
1463 *bp = 0;
1464 printf("%s\n", buf);
1465 }
1466
1467 static void
1468 ppp_ifstart(struct ifnet *ifp)
1469 {
1470 struct ppp_softc *sc;
1471
1472 sc = ifp->if_softc;
1473 (*sc->sc_start)(sc);
1474 }
1475
1476 void
1477 ppp_pkt_list_init(struct ppp_pkt_list *pl, u_int limit)
1478 {
1479 mtx_init(&pl->pl_mtx, IPL_TTY);
1480 pl->pl_head = pl->pl_tail = NULL;
1481 pl->pl_count = 0;
1482 pl->pl_limit = limit;
1483 }
1484
1485 int
1486 ppp_pkt_enqueue(struct ppp_pkt_list *pl, struct ppp_pkt *pkt)
1487 {
1488 int drop = 0;
1489
1490 mtx_enter(&pl->pl_mtx);
1491 if (pl->pl_count < pl->pl_limit) {
1492 if (pl->pl_tail == NULL)
1493 pl->pl_head = pl->pl_tail = pkt;
1494 else {
1495 PKT_NEXTPKT(pl->pl_tail) = pkt;
1496 pl->pl_tail = pkt;
1497 }
1498 PKT_NEXTPKT(pkt) = NULL;
1499 pl->pl_count++;
1500 } else
1501 drop = 1;
1502 mtx_leave(&pl->pl_mtx);
1503
1504 if (drop)
1505 ppp_pkt_free(pkt);
1506
1507 return (drop);
1508 }
1509
1510 struct ppp_pkt *
1511 ppp_pkt_dequeue(struct ppp_pkt_list *pl)
1512 {
1513 struct ppp_pkt *pkt;
1514
1515 mtx_enter(&pl->pl_mtx);
1516 pkt = pl->pl_head;
1517 if (pkt != NULL) {
1518 pl->pl_head = PKT_NEXTPKT(pkt);
1519 if (pl->pl_head == NULL)
1520 pl->pl_tail = NULL;
1521
1522 pl->pl_count--;
1523 }
1524 mtx_leave(&pl->pl_mtx);
1525
1526 return (pkt);
1527 }
1528
1529 struct mbuf *
1530 ppp_pkt_mbuf(struct ppp_pkt *pkt0)
1531 {
1532 extern struct pool ppp_pkts;
1533 struct mbuf *m0 = NULL, **mp = &m0, *m;
1534 struct ppp_pkt *pkt = pkt0;
1535 size_t len = 0;
1536
1537 do {
1538 MGETHDR(m, M_DONTWAIT, MT_DATA);
1539 if (m == NULL)
1540 goto fail;
1541
1542 MEXTADD(m, pkt, sizeof(*pkt), M_EXTWR,
1543 MEXTFREE_POOL, &ppp_pkts);
1544 m->m_data += sizeof(pkt->p_hdr);
1545 m->m_len = PKT_LEN(pkt);
1546
1547 len += m->m_len;
1548
1549 *mp = m;
1550 mp = &m->m_next;
1551
1552 pkt = PKT_NEXT(pkt);
1553 } while (pkt != NULL);
1554
1555 m0->m_pkthdr.len = len;
1556 if (pkt0->p_hdr.ph_errmark)
1557 m0->m_flags |= M_ERRMARK;
1558
1559 return (m0);
1560
1561 fail:
1562 m_freem(m0);
1563 ppp_pkt_free(pkt0);
1564 return (NULL);
1565 }
1566
1567 #endif /* NPPP > 0 */
Cache object: 37538c92117b85ed070e8d7810fb9db1
|