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