Bug Summary

File:net/if_ppp.c
Warning:line 1375, column 2
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_ppp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/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 NPPP1 > 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 PACKETPTRstruct mbuf * struct mbuf *
144#include <net/ppp-comp.h>
145#endif
146
147static int pppsioctl(struct ifnet *, u_long, caddr_t);
148static void ppp_requeue(struct ppp_softc *);
149static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd);
150static void ppp_ccp_closed(struct ppp_softc *);
151static void ppp_inproc(struct ppp_softc *, struct mbuf *);
152static void pppdumpm(struct mbuf *m0);
153static void ppp_ifstart(struct ifnet *ifp);
154int ppp_clone_create(struct if_clone *, int);
155int ppp_clone_destroy(struct ifnet *);
156
157void ppp_pkt_list_init(struct ppp_pkt_list *, u_int);
158int ppp_pkt_enqueue(struct ppp_pkt_list *, struct ppp_pkt *);
159struct ppp_pkt *ppp_pkt_dequeue(struct ppp_pkt_list *);
160struct 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_ERRMARK0x8000 M_LINK00x8000 /* steal a bit in mbuf m_flags */
167
168
169#ifdef PPP_COMPRESS
170/*
171 * List of compressors we know about.
172 */
173
174extern struct compressor ppp_bsd_compress;
175extern struct compressor ppp_deflate, ppp_deflate_draft;
176
177struct compressor *ppp_compressors[] = {
178#if DO_BSD_COMPRESS1 && defined(PPP_BSDCOMP1)
179 &ppp_bsd_compress,
180#endif
181#if DO_DEFLATE1 && defined(PPP_DEFLATE1)
182 &ppp_deflate,
183 &ppp_deflate_draft,
184#endif
185 NULL((void *)0)
186};
187#endif /* PPP_COMPRESS */
188
189LIST_HEAD(, ppp_softc)struct { struct ppp_softc *lh_first; } ppp_softc_list;
190struct if_clone ppp_cloner =
191 IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy){ .ifc_list = { ((void *)0), ((void *)0) }, .ifc_name = "ppp"
, .ifc_namelen = sizeof("ppp") - 1, .ifc_create = ppp_clone_create
, .ifc_destroy = ppp_clone_destroy, }
;
192
193/*
194 * Called from boot code to establish ppp interfaces.
195 */
196void
197pppattach(void)
198{
199 LIST_INIT(&ppp_softc_list)do { ((&ppp_softc_list)->lh_first) = ((void *)0); } while
(0)
;
200 if_clone_attach(&ppp_cloner);
201}
202
203int
204ppp_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_DEVBUF2, M_WAITOK0x0001|M_ZERO0x0008);
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_mtuif_data.ifi_mtu = PPP_MTU1500;
216 sc->sc_if.if_flags = IFF_POINTOPOINT0x10 | IFF_MULTICAST0x8000;
217 sc->sc_if.if_typeif_data.ifi_type = IFT_PPP0x17;
218 sc->sc_if.if_hdrlenif_data.ifi_hdrlen = PPP_HDRLEN4;
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_MAXLEN256, IPL_NET0x7);
224 ppp_pkt_list_init(&sc->sc_rawq, IFQ_MAXLEN256);
225 if_attach(&sc->sc_if);
226 if_alloc_sadl(&sc->sc_if);
227#if NBPFILTER1 > 0
228 bpfattach(&ifp->if_bpf, ifp, DLT_PPP9, PPP_HDRLEN4);
229#endif
230 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
231 LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_list)do { if (((sc)->sc_list.le_next = (&ppp_softc_list)->
lh_first) != ((void *)0)) (&ppp_softc_list)->lh_first->
sc_list.le_prev = &(sc)->sc_list.le_next; (&ppp_softc_list
)->lh_first = (sc); (sc)->sc_list.le_prev = &(&
ppp_softc_list)->lh_first; } while (0)
;
232 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
233
234 return (0);
235}
236
237int
238ppp_clone_destroy(struct ifnet *ifp)
239{
240 struct ppp_softc *sc = ifp->if_softc;
241
242 if (sc->sc_devp != NULL((void *)0))
243 return (EBUSY16);
244
245 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
246 LIST_REMOVE(sc, sc_list)do { if ((sc)->sc_list.le_next != ((void *)0)) (sc)->sc_list
.le_next->sc_list.le_prev = (sc)->sc_list.le_prev; *(sc
)->sc_list.le_prev = (sc)->sc_list.le_next; ((sc)->sc_list
.le_prev) = ((void *)-1); ((sc)->sc_list.le_next) = ((void
*)-1); } while (0)
;
247 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
248
249 if_detach(ifp);
250
251 free(sc, M_DEVBUF2, 0);
252 return (0);
253}
254
255/*
256 * Allocate a ppp interface unit and initialize it.
257 */
258struct ppp_softc *
259pppalloc(pid_t pid)
260{
261 int i;
262 struct ppp_softc *sc;
263
264 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
265 LIST_FOREACH(sc, &ppp_softc_list, sc_list)for((sc) = ((&ppp_softc_list)->lh_first); (sc)!= ((void
*)0); (sc) = ((sc)->sc_list.le_next))
{
266 if (sc->sc_xfer == pid) {
267 sc->sc_xfer = 0;
268 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
269 return sc;
270 }
271 }
272 LIST_FOREACH(sc, &ppp_softc_list, sc_list)for((sc) = ((&ppp_softc_list)->lh_first); (sc)!= ((void
*)0); (sc) = ((sc)->sc_list.le_next))
{
273 if (sc->sc_devp == NULL((void *)0))
274 break;
275 }
276 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
277 if (sc == NULL((void *)0))
278 return NULL((void *)0);
279
280 sc->sc_flags = 0;
281 sc->sc_mru = PPP_MRU1500;
282 sc->sc_relinq = NULL((void *)0);
283 bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats))__builtin_bzero(((char *)&sc->sc_stats), (sizeof(sc->
sc_stats)))
;
284#ifdef VJC
285 sc->sc_comp = malloc(sizeof(struct slcompress), M_DEVBUF2, M_NOWAIT0x0002);
286 if (sc->sc_comp)
287 sl_compress_init(sc->sc_comp);
288#endif
289#ifdef PPP_COMPRESS
290 sc->sc_xc_state = NULL((void *)0);
291 sc->sc_rc_state = NULL((void *)0);
292#endif /* PPP_COMPRESS */
293 for (i = 0; i < NUM_NP1; ++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 */
304void
305pppdealloc(struct ppp_softc *sc)
306{
307 struct ppp_pkt *pkt;
308
309 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
310 if_down(&sc->sc_if);
311 sc->sc_if.if_flags &= ~IFF_RUNNING0x40;
312 sc->sc_devp = NULL((void *)0);
313 sc->sc_xfer = 0;
314 while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL((void *)0))
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((void *)0);
320
321#ifdef PPP_COMPRESS
322 ppp_ccp_closed(sc);
323 sc->sc_xc_state = NULL((void *)0);
324 sc->sc_rc_state = NULL((void *)0);
325#endif /* PPP_COMPRESS */
326#if NBPFILTER1 > 0
327 if (sc->sc_pass_filt.bf_insns != 0) {
328 free(sc->sc_pass_filt.bf_insns, M_DEVBUF2, 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_DEVBUF2, 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_DEVBUF2, 0);
341 sc->sc_comp = 0;
342 }
343#endif
344 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
345}
346
347/*
348 * Ioctl routine for generic ppp devices.
349 */
350int
351pppioctl(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 NBPFILTER1 > 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_LENGTH32];
367#endif
368
369 switch (cmd) {
370 case FIONREAD((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((127)))
:
371 *(int *)data = mq_len(&sc->sc_inq)((&(&sc->sc_inq)->mq_list)->ml_len);
372 break;
373
374 case PPPIOCGUNIT((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((86)))
:
375 *(int *)data = sc->sc_unit; /* XXX */
376 break;
377
378 case PPPIOCGFLAGS((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((90)))
:
379 *(u_int *)data = sc->sc_flags;
380 break;
381
382 case PPPIOCSFLAGS((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((89)))
:
383 if ((error = suser(p)) != 0)
384 return (error);
385 flags = *(int *)data & SC_MASK0x0fff00ff;
386#ifdef PPP_COMPRESS
387 if (sc->sc_flags & SC_CCP_OPEN0x00000040 && !(flags & SC_CCP_OPEN0x00000040))
388 ppp_ccp_closed(sc);
389#endif
390 s = splnet()splraise(0x7);
391 sc->sc_flags = (sc->sc_flags & ~SC_MASK0x0fff00ff) | flags;
392 splx(s)spllower(s);
393 break;
394
395 case PPPIOCSMRU((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((82)))
:
396 if ((error = suser(p)) != 0)
397 return (error);
398 mru = *(int *)data;
399 if (mru >= PPP_MRU1500 && mru <= PPP_MAXMRU65000)
400 sc->sc_mru = mru;
401 break;
402
403 case PPPIOCGMRU((unsigned long)0x40000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((83)))
:
404 *(int *)data = sc->sc_mru;
405 break;
406
407#ifdef VJC
408 case PPPIOCSMAXCID((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('t')) << 8) | ((81)))
:
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((unsigned long)0x20000000 | ((0 & 0x1fff) << 16) |
((('t')) << 8) | ((78)))
:
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((unsigned long)0x80000000 | ((sizeof(struct ppp_option_data)
& 0x1fff) << 16) | ((('t')) << 8) | ((77)))
:
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 (EINVAL22);
435 for (cp = ppp_compressors; *cp != NULL((void *)0); ++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((void *)0)) {
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((void *)0)) {
451 if (sc->sc_flags & SC_DEBUG0x00010000)
452 printf(
453 "%s: comp_alloc failed\n",
454 sc->sc_if.if_xname);
455 error = ENOBUFS55;
456 }
457 s = splnet()splraise(0x7);
458 sc->sc_flags &= ~SC_COMP_RUN0x00001000;
459 splx(s)spllower(s);
460 } else {
461 if (sc->sc_rc_state != NULL((void *)0)) {
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((void *)0)) {
469 if (sc->sc_flags & SC_DEBUG0x00010000) {
470 printf(
471 "%s: decomp_alloc failed\n",
472 sc->sc_if.if_xname);
473 }
474 error = ENOBUFS55;
475 }
476 s = splnet()splraise(0x7);
477 sc->sc_flags &= ~SC_DECOMP_RUN0x00002000;
478 splx(s)spllower(s);
479 }
480 return (error);
481 }
482 if (sc->sc_flags & SC_DEBUG0x00010000) {
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 (EINVAL22); /* no handler found */
488#endif /* PPP_COMPRESS */
489
490 case PPPIOCGNPMODE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct npioctl) & 0x1fff) << 16) | ((('t')) <<
8) | ((76)))
:
491 case PPPIOCSNPMODE((unsigned long)0x80000000 | ((sizeof(struct npioctl) & 0x1fff
) << 16) | ((('t')) << 8) | ((75)))
:
492 npi = (struct npioctl *)data;
493 switch (npi->protocol) {
494 case PPP_IP0x21:
495 npx = NP_IP0;
496 break;
497 default:
498 return EINVAL22;
499 }
500 if (cmd == PPPIOCGNPMODE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct npioctl) & 0x1fff) << 16) | ((('t')) <<
8) | ((76)))
) {
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((unsigned long)0x40000000 | ((sizeof(struct ppp_idle) & 0x1fff
) << 16) | ((('t')) << 8) | ((74)))
:
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 NBPFILTER1 > 0
522 case PPPIOCSPASS((unsigned long)0x80000000 | ((sizeof(struct bpf_program) &
0x1fff) << 16) | ((('t')) << 8) | ((71)))
:
523 case PPPIOCSACTIVE((unsigned long)0x80000000 | ((sizeof(struct bpf_program) &
0x1fff) << 16) | ((('t')) << 8) | ((70)))
:
524 nbp = (struct bpf_program *) data;
525 if ((unsigned) nbp->bf_len > BPF_MAXINSNS512)
526 return EINVAL22;
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_DEVBUF2, M_WAITOK0x0001);
531 if ((error = copyin((caddr_t)nbp->bf_insns,
532 (caddr_t)newcode, newcodelen)) != 0) {
533 free(newcode, M_DEVBUF2, 0);
534 return error;
535 }
536 if (!bpf_validate(newcode, nbp->bf_len)) {
537 free(newcode, M_DEVBUF2, 0);
538 return EINVAL22;
539 }
540 } else
541 newcode = 0;
542 bp = (cmd == PPPIOCSPASS((unsigned long)0x80000000 | ((sizeof(struct bpf_program) &
0x1fff) << 16) | ((('t')) << 8) | ((71)))
) ?
543 &sc->sc_pass_filt : &sc->sc_active_filt;
544 oldcode = bp->bf_insns;
545 s = splnet()splraise(0x7);
546 bp->bf_len = nbp->bf_len;
547 bp->bf_insns = newcode;
548 splx(s)spllower(s);
549 if (oldcode != 0)
550 free(oldcode, M_DEVBUF2, 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 */
563static int
564pppsioctl(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()splraise(0x7), error = 0;
574
575 switch (cmd) {
576 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
577 if ((ifp->if_flags & IFF_RUNNING0x40) == 0)
578 ifp->if_flags &= ~IFF_UP0x1;
579 break;
580
581 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
582 if (ifa->ifa_addr->sa_family != AF_INET2)
583 error = EAFNOSUPPORT47;
584 break;
585
586 case SIOCSIFDSTADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((14)))
:
587 if (ifa->ifa_addr->sa_family != AF_INET2)
588 error = EAFNOSUPPORT47;
589 break;
590
591 case SIOCSIFMTU((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((127)))
:
592 sc->sc_if.if_mtuif_data.ifi_mtu = ifr->ifr_mtuifr_ifru.ifru_metric;
593 break;
594
595 case SIOCADDMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((49)))
:
596 case SIOCDELMULTI((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((50)))
:
597 break;
598
599 case SIOCGPPPSTATS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifpppstatsreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((123)))
:
600 psp = &((struct ifpppstatsreq *) data)->stats;
601 bzero(psp, sizeof(*psp))__builtin_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(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifpppcstatsreq) & 0x1fff) << 16) | ((('i'))
<< 8) | ((122)))
:
621 pcp = &((struct ifpppcstatsreq *) data)->stats;
622 bzero(pcp, sizeof(*pcp))__builtin_bzero((pcp), (sizeof(*pcp)));
623 if (sc->sc_xc_state != NULL((void *)0))
624 (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
625 if (sc->sc_rc_state != NULL((void *)0))
626 (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
627 break;
628#endif /* PPP_COMPRESS */
629
630 default:
631 error = ENOTTY25;
632 }
633 splx(s)spllower(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 */
641int
642pppoutput(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((void *)0) || (ifp->if_flags & IFF_RUNNING0x40) == 0
653 || ((ifp->if_flags & IFF_UP0x1) == 0 && dst->sa_family != AF_UNSPEC0)) {
654 error = ENETDOWN50; /* sort of */
655 goto bad;
656 }
657
658#ifdef DIAGNOSTIC1
659 if (ifp->if_rdomainif_data.ifi_rdomain != rtable_l2(m0->m_pkthdrM_dat.MH.MH_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_rdomainif_data.ifi_rdomain, rtable_l2(m0->m_pkthdrM_dat.MH.MH_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_INET2:
672 address = PPP_ALLSTATIONS0xff;
673 control = PPP_UI0x03;
674 protocol = PPP_IP0x21;
675 mode = sc->sc_npmode[NP_IP0];
676 break;
677 case AF_UNSPEC0:
678 address = PPP_ADDRESS(dst->sa_data)(((u_char *)(dst->sa_data))[0]);
679 control = PPP_CONTROL(dst->sa_data)(((u_char *)(dst->sa_data))[1]);
680 protocol = PPP_PROTOCOL(dst->sa_data)((((u_char *)(dst->sa_data))[2] << 8) + ((u_char *)(
dst->sa_data))[3])
;
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 = EAFNOSUPPORT47;
687 goto bad;
688 }
689
690 /*
691 * Drop this packet, or return an error, if necessary.
692 */
693 if (mode == NPMODE_ERROR) {
694 error = ENETDOWN50;
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)(m0) = m_prepend((m0), (4), (0x0002));
706 if (m0 == NULL((void *)0)) {
707 error = ENOBUFS55;
708 goto bad;
709 }
710
711 cp = mtod(m0, u_char *)((u_char *)((m0)->m_hdr.mh_data));
712 *cp++ = address;
713 *cp++ = control;
714 *cp++ = protocol >> 8;
715 *cp++ = protocol & 0xff;
716
717 if ((m0->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002) == 0)
718 panic("mbuf packet without packet header!");
719 len = m0->m_pkthdrM_dat.MH.MH_pkthdr.len;
720
721 if (sc->sc_flags & SC_LOG_OUTPKT0x00040000) {
722 printf("%s output: ", ifp->if_xname);
723 pppdumpm(m0);
724 }
725
726 if ((protocol & 0x8000) == 0) {
727#if NBPFILTER1 > 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 *)((u_char *)((m0)->m_hdr.mh_data)) = 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 *)((u_char *)((m0)->m_hdr.mh_data)) = 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 NBPFILTER1 > 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(1 << 1));
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_oerrorsif_data.ifi_oerrors++;
773 sc->sc_stats.ppp_oerrors++;
774 return (error);
775 }
776 (*sc->sc_start)(sc);
777 }
778 ifp->if_opacketsif_data.ifi_opackets++;
779 ifp->if_obytesif_data.ifi_obytes += len;
780
781 return (0);
782
783bad:
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 */
794static void
795ppp_requeue(struct ppp_softc *sc)
796{
797 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
798 struct mbuf *m;
799 enum NPmode mode;
800 int error;
801
802 while ((m = ml_dequeue(&sc->sc_npqueue)) != NULL((void *)0)) {
803 switch (PPP_PROTOCOL(mtod(m, u_char *))((((u_char *)(((u_char *)((m)->m_hdr.mh_data))))[2] <<
8) + ((u_char *)(((u_char *)((m)->m_hdr.mh_data))))[3])
) {
804 case PPP_IP0x21:
805 mode = sc->sc_npmode[NP_IP0];
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_oerrorsif_data.ifi_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 */
836void
837ppp_restart(struct ppp_softc *sc)
838{
839 int s = splnet()splraise(0x7);
840
841 sc->sc_flags &= ~SC_TBUSY0x10000000;
842 schednetisr(NETISR_PPP)do { x86_atomic_setbits_u32(&netisr, (1 << (28))); task_add
(net_tq(0), &if_input_task_locked); } while ( 0)
;
843 splx(s)spllower(s);
844}
845
846/*
847 * Get a packet to send.
848 */
849struct mbuf *
850ppp_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((void *)0))
862 return NULL((void *)0);
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 *)((u_char *)((m)->m_hdr.mh_data));
871 address = PPP_ADDRESS(cp)(((u_char *)(cp))[0]);
872 control = PPP_CONTROL(cp)(((u_char *)(cp))[1]);
873 protocol = PPP_PROTOCOL(cp)((((u_char *)(cp))[2] << 8) + ((u_char *)(cp))[3]);
874
875 switch (protocol) {
876 case PPP_IP0x21:
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_TCP0x00000004) && sc->sc_comp != NULL((void *)0)) {
882 struct ip *ip;
883 int type;
884
885 mp = m;
886 ip = (struct ip *)(cp + PPP_HDRLEN4);
887 if (mp->m_lenm_hdr.mh_len <= PPP_HDRLEN4) {
888 mp = mp->m_nextm_hdr.mh_next;
889 if (mp == NULL((void *)0))
890 break;
891 ip = mtod(mp, struct ip *)((struct ip *)((mp)->m_hdr.mh_data));
892 }
893 /*
894 * this code assumes the IP/TCP header is in one
895 * non-shared mbuf.
896 */
897 if (ip->ip_p == IPPROTO_TCP6) {
898 type = sl_compress_tcp(mp, ip, sc->sc_comp,
899 !(sc->sc_flags & SC_NO_TCP_CCID0x00000008));
900 switch (type) {
901 case TYPE_UNCOMPRESSED_TCP0x70:
902 protocol = PPP_VJC_UNCOMP0x2f;
903 break;
904 case TYPE_COMPRESSED_TCP0x80:
905 protocol = PPP_VJC_COMP0x2d;
906 cp = mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data));
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_CCP0x80fd:
921 ppp_ccp(sc, m, 0);
922 break;
923#endif /* PPP_COMPRESS */
924 }
925
926#ifdef PPP_COMPRESS
927 if (protocol != PPP_LCP0xc021 && protocol != PPP_CCP0x80fd &&
928 sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN0x00001000)) {
929 struct mbuf *mcomp = NULL((void *)0);
930 int slen;
931
932 slen = 0;
933 for (mp = m; mp != NULL((void *)0); mp = mp->m_nextm_hdr.mh_next)
934 slen += mp->m_lenm_hdr.mh_len;
935 (*sc->sc_xcomp->compress)(sc->sc_xc_state, &mcomp, m, slen,
936 (sc->sc_flags & SC_CCP_UP0x00000080 ?
937 sc->sc_if.if_mtuif_data.ifi_mtu + PPP_HDRLEN4 : 0));
938 if (mcomp != NULL((void *)0)) {
939 if (sc->sc_flags & SC_CCP_UP0x00000080) {
940 /* Send the compressed packet instead. */
941 m_freem(m);
942 m = mcomp;
943 cp = mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data));
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_AC0x00000002 && address == PPP_ALLSTATIONS0xff &&
960 control == PPP_UI0x03 && protocol != PPP_ALLSTATIONS0xff &&
961 protocol != PPP_LCP0xc021) {
962 /* can compress address/control */
963 m->m_datam_hdr.mh_data += 2;
964 m->m_lenm_hdr.mh_len -= 2;
965 }
966 if (sc->sc_flags & SC_COMP_PROT0x00000001 && protocol < 0xFF) {
967 /* can compress protocol */
968 if (mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data)) == cp) {
969 cp[2] = cp[1]; /* move address/control up */
970 cp[1] = cp[0];
971 }
972 ++m->m_datam_hdr.mh_data;
973 --m->m_lenm_hdr.mh_len;
974 }
975
976 return m;
977}
978
979/*
980 * Software interrupt routine.
981 */
982void
983pppintr(void)
984{
985 struct ppp_softc *sc;
986 int s;
987 struct ppp_pkt *pkt;
988 struct mbuf *m;
989
990 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
991
992 LIST_FOREACH(sc, &ppp_softc_list, sc_list)for((sc) = ((&ppp_softc_list)->lh_first); (sc)!= ((void
*)0); (sc) = ((sc)->sc_list.le_next))
{
993 if (!(sc->sc_flags & SC_TBUSY0x10000000) &&
994 (!ifq_empty(&sc->sc_if.if_snd)(((&sc->sc_if.if_snd)->ifq_len) == 0))) {
995 s = splnet()splraise(0x7);
996 sc->sc_flags |= SC_TBUSY0x10000000;
997 splx(s)spllower(s);
998 (*sc->sc_start)(sc);
999 }
1000 while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL((void *)0)) {
1001 m = ppp_pkt_mbuf(pkt);
1002 if (m == NULL((void *)0))
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 */
1014static void
1015ppp_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_lenm_hdr.mh_len <= PPP_HDRLEN4) {
1025 mp = m->m_nextm_hdr.mh_next;
1026 if (mp == NULL((void *)0))
1027 return;
1028 dp = mtod(mp, u_char *)((u_char *)((mp)->m_hdr.mh_data));
1029 } else {
1030 mp = m;
1031 dp = mtod(mp, u_char *)((u_char *)((mp)->m_hdr.mh_data)) + PPP_HDRLEN4;
1032 }
1033
1034 ep = mtod(mp, u_char *)((u_char *)((mp)->m_hdr.mh_data)) + mp->m_lenm_hdr.mh_len;
1035 if (dp + CCP_HDRLEN4 > ep)
1036 return;
1037 slen = CCP_LENGTH(dp)(((dp)[2] << 8) + (dp)[3]);
1038 if (dp + slen > ep) {
1039 if (sc->sc_flags & SC_DEBUG0x00010000) {
1040 printf("if_ppp/ccp: not enough data in mbuf"
1041 " (%p+%x > %p+%x)\n", dp, slen,
1042 mtod(mp, u_char *)((u_char *)((mp)->m_hdr.mh_data)), mp->m_lenm_hdr.mh_len);
1043 }
1044 return;
1045 }
1046
1047 switch (CCP_CODE(dp)((dp)[0])) {
1048 case CCP_CONFREQ1:
1049 case CCP_TERMREQ5:
1050 case CCP_TERMACK6:
1051 /* CCP must be going down - disable compression */
1052 if (sc->sc_flags & SC_CCP_UP0x00000080) {
1053 s = splnet()splraise(0x7);
1054 sc->sc_flags &=
1055 ~(SC_CCP_UP0x00000080 | SC_COMP_RUN0x00001000 | SC_DECOMP_RUN0x00002000);
1056 splx(s)spllower(s);
1057 }
1058 break;
1059
1060 case CCP_CONFACK2:
1061 if (sc->sc_flags & SC_CCP_OPEN0x00000040 &&
1062 !(sc->sc_flags & SC_CCP_UP0x00000080) &&
1063 slen >= CCP_HDRLEN4 + CCP_OPT_MINLEN2 &&
1064 slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN)((dp + 4)[1]) + CCP_HDRLEN4) {
1065 if (!rcvd) {
1066 /* we're agreeing to send compressed packets. */
1067 if (sc->sc_xc_state != NULL((void *)0) &&
1068 (*sc->sc_xcomp->comp_init)(sc->sc_xc_state,
1069 dp + CCP_HDRLEN4, slen - CCP_HDRLEN4,
1070 sc->sc_unit, 0, sc->sc_flags & SC_DEBUG0x00010000)) {
1071 s = splnet()splraise(0x7);
1072 sc->sc_flags |= SC_COMP_RUN0x00001000;
1073 splx(s)spllower(s);
1074 }
1075 } else {
1076 /* peer agrees to send compressed packets */
1077 if (sc->sc_rc_state != NULL((void *)0) &&
1078 (*sc->sc_rcomp->decomp_init)(
1079 sc->sc_rc_state, dp + CCP_HDRLEN4,
1080 slen - CCP_HDRLEN4, sc->sc_unit, 0,
1081 sc->sc_mru, sc->sc_flags & SC_DEBUG0x00010000)) {
1082 s = splnet()splraise(0x7);
1083 sc->sc_flags |= SC_DECOMP_RUN0x00002000;
1084 sc->sc_flags &=
1085 ~(SC_DC_ERROR0x00004000 | SC_DC_FERROR0x00008000);
1086 splx(s)spllower(s);
1087 }
1088 }
1089 }
1090 break;
1091
1092 case CCP_RESETACK15:
1093 if (sc->sc_flags & SC_CCP_UP0x00000080) {
1094 if (!rcvd) {
1095 if (sc->sc_xc_state &&
1096 (sc->sc_flags & SC_COMP_RUN0x00001000)) {
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_RUN0x00002000)) {
1103 (*sc->sc_rcomp->decomp_reset)(
1104 sc->sc_rc_state);
1105 s = splnet()splraise(0x7);
1106 sc->sc_flags &= ~SC_DC_ERROR0x00004000;
1107 splx(s)spllower(s);
1108 }
1109 }
1110 }
1111 break;
1112 }
1113}
1114
1115/*
1116 * CCP is down; free (de)compressor state if necessary.
1117 */
1118static void
1119ppp_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((void *)0);
1124 }
1125 if (sc->sc_rc_state) {
1126 (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
1127 sc->sc_rc_state = NULL((void *)0);
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 */
1138void
1139ppppktin(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)do { x86_atomic_setbits_u32(&netisr, (1 << (28))); task_add
(net_tq(0), &if_input_task_locked); } while ( 0)
;
1144}
1145
1146/*
1147 * Process a received PPP packet, doing decompression as necessary.
1148 */
1149#define COMPTYPE(proto)((proto) == 0x2d? 0x80: 0x70) ((proto) == PPP_VJC_COMP0x2d? TYPE_COMPRESSED_TCP0x80: \
1150 TYPE_UNCOMPRESSED_TCP0x70)
1151
1152static void
1153ppp_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((void *)0);
1159 u_char *iphdr;
1160 u_int hlen;
1161
1162 sc->sc_stats.ppp_ipackets++;
1163
1164 if (sc->sc_flags & SC_LOG_INPKT0x00020000) {
1165 ilen = 0;
1166 for (mp = m; mp != NULL((void *)0); mp = mp->m_nextm_hdr.mh_next)
1167 ilen += mp->m_lenm_hdr.mh_len;
1168 printf("%s: got %d bytes\n", ifp->if_xname, ilen);
1169 pppdumpm(m);
1170 }
1171
1172 cp = mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data));
1173 adrs = PPP_ADDRESS(cp)(((u_char *)(cp))[0]);
1174 ctrl = PPP_CONTROL(cp)(((u_char *)(cp))[1]);
1175 proto = PPP_PROTOCOL(cp)((((u_char *)(cp))[2] << 8) + ((u_char *)(cp))[3]);
1176
1177 if (m->m_flagsm_hdr.mh_flags & M_ERRMARK0x8000) {
1178 m->m_flagsm_hdr.mh_flags &= ~M_ERRMARK0x8000;
1179 s = splnet()splraise(0x7);
1180 sc->sc_flags |= SC_VJ_RESET0x00000800;
1181 splx(s)spllower(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_COMP0xfd && sc->sc_rc_state &&
1190 (sc->sc_flags & SC_DECOMP_RUN0x00002000) && !(sc->sc_flags & SC_DC_ERROR0x00004000) &&
1191 !(sc->sc_flags & SC_DC_FERROR0x00008000)) {
1192 /* decompress this packet */
1193 rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
1194 if (rv == DECOMP_OK0) {
1195 m_freem(m);
1196 if (dmp == NULL((void *)0)) {
1197 /*
1198 * no error, but no decompressed packet
1199 * produced
1200 */
1201 return;
1202 }
1203 m = dmp;
1204 cp = mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data));
1205 proto = PPP_PROTOCOL(cp)((((u_char *)(cp))[2] << 8) + ((u_char *)(cp))[3]);
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_DEBUG0x00010000) {
1214 printf("%s: decompress failed %d\n",
1215 ifp->if_xname, rv);
1216 }
1217 s = splnet()splraise(0x7);
1218 sc->sc_flags |= SC_VJ_RESET0x00000800;
1219 if (rv == DECOMP_ERROR1)
1220 sc->sc_flags |= SC_DC_ERROR0x00004000;
1221 else
1222 sc->sc_flags |= SC_DC_FERROR0x00008000;
1223 splx(s)spllower(s);
1224 }
1225
1226 } else {
1227 if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN0x00002000)) {
1228 (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
1229 }
1230 if (proto == PPP_CCP0x80fd) {
1231 ppp_ccp(sc, m, 1);
1232 }
1233 }
1234#endif
1235
1236 ilen = 0;
1237 for (mp = m; mp != NULL((void *)0); mp = mp->m_nextm_hdr.mh_next)
1238 ilen += mp->m_lenm_hdr.mh_len;
1239
1240#ifdef VJC
1241 if (sc->sc_flags & SC_VJ_RESET0x00000800) {
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((void *)0), 0, TYPE_ERROR0x00, sc->sc_comp);
1248 s = splnet()splraise(0x7);
1249 sc->sc_flags &= ~SC_VJ_RESET0x00000800;
1250 splx(s)spllower(s);
1251 }
1252
1253 /*
1254 * See if we have a VJ-compressed packet to uncompress.
1255 */
1256 if (proto == PPP_VJC_COMP0x2d) {
1257 if ((sc->sc_flags & SC_REJ_COMP_TCP0x00000020) || sc->sc_comp == 0)
1258 goto bad;
1259
1260 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN4,
1261 m->m_lenm_hdr.mh_len - PPP_HDRLEN4, ilen - PPP_HDRLEN4,
1262 TYPE_COMPRESSED_TCP0x80, sc->sc_comp, &iphdr, &hlen);
1263
1264 if (xlen <= 0) {
1265 if (sc->sc_flags & SC_DEBUG0x00010000) {
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)mp = m_gethdr((0x0002), (1));
1274 if (mp == NULL((void *)0))
1275 goto bad;
1276 mp->m_lenm_hdr.mh_len = 0;
1277 mp->m_nextm_hdr.mh_next = NULL((void *)0);
1278 if (hlen + PPP_HDRLEN4 > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
1279 MCLGET(mp, M_DONTWAIT)(void) m_clget((mp), (0x0002), (1 << 11));
1280 if (m_trailingspace(mp) < hlen + PPP_HDRLEN4) {
1281 m_freem(mp);
1282 /* lose if big headers and no clusters */
1283 goto bad;
1284 }
1285 }
1286 if (m->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002)
1287 M_MOVE_HDR(mp, m)do { (mp)->M_dat.MH.MH_pkthdr = (m)->M_dat.MH.MH_pkthdr
; (m)->m_hdr.mh_flags &= ~0x0002; { ((&(m)->M_dat
.MH.MH_pkthdr.ph_tags)->slh_first) = ((void *)0); }; (m)->
M_dat.MH.MH_pkthdr.pf.statekey = ((void *)0); } while ( 0)
;
1288 cp = mtod(mp, u_char *)((u_char *)((mp)->m_hdr.mh_data));
1289 cp[0] = adrs;
1290 cp[1] = ctrl;
1291 cp[2] = 0;
1292 cp[3] = PPP_IP0x21;
1293 proto = PPP_IP0x21;
1294 bcopy(iphdr, cp + PPP_HDRLEN4, hlen);
1295 mp->m_lenm_hdr.mh_len = hlen + PPP_HDRLEN4;
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_datam_hdr.mh_data += PPP_HDRLEN4 + xlen;
1302 m->m_lenm_hdr.mh_len -= PPP_HDRLEN4 + xlen;
1303 if (m->m_lenm_hdr.mh_len <= m_trailingspace(mp)) {
1304 bcopy(mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data)),
1305 mtod(mp, u_char *)((u_char *)((mp)->m_hdr.mh_data)) + mp->m_lenm_hdr.mh_len, m->m_lenm_hdr.mh_len);
1306 mp->m_lenm_hdr.mh_len += m->m_lenm_hdr.mh_len;
1307 mp->m_nextm_hdr.mh_next = m_free(m);
1308 } else
1309 mp->m_nextm_hdr.mh_next = m;
1310 m = mp;
1311 ilen += hlen - xlen;
1312
1313 } else if (proto == PPP_VJC_UNCOMP0x2f) {
1314 if ((sc->sc_flags & SC_REJ_COMP_TCP0x00000020) || sc->sc_comp == 0)
1315 goto bad;
1316
1317 xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN4,
1318 m->m_lenm_hdr.mh_len - PPP_HDRLEN4, ilen - PPP_HDRLEN4,
1319 TYPE_UNCOMPRESSED_TCP0x70, sc->sc_comp, &iphdr, &hlen);
1320
1321 if (xlen < 0) {
1322 if (sc->sc_flags & SC_DEBUG0x00010000) {
1323 printf("%s: VJ uncompress failed "
1324 "on type uncomp\n", ifp->if_xname);
1325 }
1326 goto bad;
1327 }
1328
1329 proto = PPP_IP0x21;
1330 cp[3] = PPP_IP0x21;
1331 }
1332#endif /* VJC */
1333
1334 m->m_pkthdrM_dat.MH.MH_pkthdr.len = ilen;
1335 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = ifp->if_index;
1336
1337 /* mark incoming routing table */
1338 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = ifp->if_rdomainif_data.ifi_rdomain;
1339
1340 if ((proto & 0x8000) == 0) {
1341#if NBPFILTER1 > 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 *)((u_char *)((m)->m_hdr.mh_data)); /* save address field */
1347 *mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data)) = 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 *)((u_char *)((m)->m_hdr.mh_data)) = 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 NBPFILTER1 > 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(1 << 0));
1373#endif
1374
1375 rv = 0;
Value stored to 'rv' is never read
1376 switch (proto) {
1377 case PPP_IP0x21:
1378 /*
1379 * IP packet - take off the ppp header and pass it up to IP.
1380 */
1381 if ((ifp->if_flags & IFF_UP0x1) == 0 ||
1382 sc->sc_npmode[NP_IP0] != NPMODE_PASS) {
1383 /* interface is down - drop the packet. */
1384 m_freem(m);
1385 return;
1386 }
1387 m->m_pkthdrM_dat.MH.MH_pkthdr.len -= PPP_HDRLEN4;
1388 m->m_datam_hdr.mh_data += PPP_HDRLEN4;
1389 m->m_lenm_hdr.mh_len -= PPP_HDRLEN4;
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_DEBUG0x00010000)
1410 printf("%s: input queue full\n", ifp->if_xname);
1411 ifp->if_iqdropsif_data.ifi_iqdrops++;
1412 goto dropped;
1413 }
1414
1415 ifp->if_ipacketsif_data.ifi_ipackets++;
1416 ifp->if_ibytesif_data.ifi_ibytes += ilen;
1417
1418 if (rv == 2)
1419 (*sc->sc_ctlp)(sc);
1420
1421 return;
1422
1423bad:
1424 m_freem(m);
1425dropped:
1426 sc->sc_if.if_ierrorsif_data.ifi_ierrors++;
1427 sc->sc_stats.ppp_ierrors++;
1428}
1429
1430#define MAX_DUMP_BYTES128 128
1431
1432static void
1433pppdumpm(struct mbuf *m0)
1434{
1435 char buf[3*MAX_DUMP_BYTES128+4];
1436 char *bp = buf;
1437 struct mbuf *m;
1438 static char digits[] = "0123456789abcdef";
1439
1440 for (m = m0; m; m = m->m_nextm_hdr.mh_next) {
1441 int l = m->m_lenm_hdr.mh_len;
1442 u_char *rptr = mtod(m, u_char *)((u_char *)((m)->m_hdr.mh_data));
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_nextm_hdr.mh_next) {
1454 if (bp > buf + sizeof(buf) - 3)
1455 goto done;
1456 *bp++ = '|';
1457 } else
1458 *bp++ = ' ';
1459 }
1460done:
1461 if (m)
1462 *bp++ = '>';
1463 *bp = 0;
1464 printf("%s\n", buf);
1465}
1466
1467static void
1468ppp_ifstart(struct ifnet *ifp)
1469{
1470 struct ppp_softc *sc;
1471
1472 sc = ifp->if_softc;
1473 (*sc->sc_start)(sc);
1474}
1475
1476void
1477ppp_pkt_list_init(struct ppp_pkt_list *pl, u_int limit)
1478{
1479 mtx_init(&pl->pl_mtx, IPL_TTY)do { (void)(((void *)0)); (void)(0); __mtx_init((&pl->
pl_mtx), ((((0x9)) > 0x0 && ((0x9)) < 0x9) ? 0x9
: ((0x9)))); } while (0)
;
1480 pl->pl_head = pl->pl_tail = NULL((void *)0);
1481 pl->pl_count = 0;
1482 pl->pl_limit = limit;
1483}
1484
1485int
1486ppp_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((void *)0))
1493 pl->pl_head = pl->pl_tail = pkt;
1494 else {
1495 PKT_NEXTPKT(pl->pl_tail)((pl->pl_tail)->p_hdr.ph_pkt) = pkt;
1496 pl->pl_tail = pkt;
1497 }
1498 PKT_NEXTPKT(pkt)((pkt)->p_hdr.ph_pkt) = NULL((void *)0);
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
1510struct ppp_pkt *
1511ppp_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((void *)0)) {
1518 pl->pl_head = PKT_NEXTPKT(pkt)((pkt)->p_hdr.ph_pkt);
1519 if (pl->pl_head == NULL((void *)0))
1520 pl->pl_tail = NULL((void *)0);
1521
1522 pl->pl_count--;
1523 }
1524 mtx_leave(&pl->pl_mtx);
1525
1526 return (pkt);
1527}
1528
1529struct mbuf *
1530ppp_pkt_mbuf(struct ppp_pkt *pkt0)
1531{
1532 extern struct pool ppp_pkts;
1533 struct mbuf *m0 = NULL((void *)0), **mp = &m0, *m;
1534 struct ppp_pkt *pkt = pkt0;
1535 size_t len = 0;
1536
1537 do {
1538 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
1539 if (m == NULL((void *)0))
1540 goto fail;
1541
1542 MEXTADD(m, pkt, sizeof(*pkt), M_EXTWR,do { (m)->m_hdr.mh_data = (m)->M_dat.MH.MH_dat.MH_ext.ext_buf
= (caddr_t)(pkt); (m)->m_hdr.mh_flags |= 0x0001 | (0x0008
& 0x0008); (m)->M_dat.MH.MH_dat.MH_ext.ext_size = (sizeof
(*pkt)); (m)->M_dat.MH.MH_dat.MH_ext.ext_free_fn = (0); (m
)->M_dat.MH.MH_dat.MH_ext.ext_arg = (&ppp_pkts); do { (
m)->M_dat.MH.MH_dat.MH_ext.ext_prevref = (m); (m)->M_dat
.MH.MH_dat.MH_ext.ext_nextref = (m); ; ; } while ( 0); } while
( 0)
1543 MEXTFREE_POOL, &ppp_pkts)do { (m)->m_hdr.mh_data = (m)->M_dat.MH.MH_dat.MH_ext.ext_buf
= (caddr_t)(pkt); (m)->m_hdr.mh_flags |= 0x0001 | (0x0008
& 0x0008); (m)->M_dat.MH.MH_dat.MH_ext.ext_size = (sizeof
(*pkt)); (m)->M_dat.MH.MH_dat.MH_ext.ext_free_fn = (0); (m
)->M_dat.MH.MH_dat.MH_ext.ext_arg = (&ppp_pkts); do { (
m)->M_dat.MH.MH_dat.MH_ext.ext_prevref = (m); (m)->M_dat
.MH.MH_dat.MH_ext.ext_nextref = (m); ; ; } while ( 0); } while
( 0)
;
1544 m->m_datam_hdr.mh_data += sizeof(pkt->p_hdr);
1545 m->m_lenm_hdr.mh_len = PKT_LEN(pkt)((pkt)->p_hdr.ph_len);
1546
1547 len += m->m_lenm_hdr.mh_len;
1548
1549 *mp = m;
1550 mp = &m->m_nextm_hdr.mh_next;
1551
1552 pkt = PKT_NEXT(pkt)((pkt)->p_hdr.ph_next);
1553 } while (pkt != NULL((void *)0));
1554
1555 m0->m_pkthdrM_dat.MH.MH_pkthdr.len = len;
1556 if (pkt0->p_hdr.ph_errmark)
1557 m0->m_flagsm_hdr.mh_flags |= M_ERRMARK0x8000;
1558
1559 return (m0);
1560
1561fail:
1562 m_freem(m0);
1563 ppp_pkt_free(pkt0);
1564 return (NULL((void *)0));
1565}
1566
1567#endif /* NPPP > 0 */