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