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