if_ppp.c revision 1.12 1 1.1 deraadt /*
2 1.1 deraadt * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
3 1.1 deraadt *
4 1.1 deraadt * Copyright (c) 1989 Carnegie Mellon University.
5 1.1 deraadt * All rights reserved.
6 1.1 deraadt *
7 1.1 deraadt * Redistribution and use in source and binary forms are permitted
8 1.1 deraadt * provided that the above copyright notice and this paragraph are
9 1.1 deraadt * duplicated in all such forms and that any documentation,
10 1.1 deraadt * advertising materials, and other materials related to such
11 1.1 deraadt * distribution and use acknowledge that the software was developed
12 1.1 deraadt * by Carnegie Mellon University. The name of the
13 1.1 deraadt * University may not be used to endorse or promote products derived
14 1.1 deraadt * from this software without specific prior written permission.
15 1.1 deraadt * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 1.1 deraadt * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 1.1 deraadt * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 1.1 deraadt *
19 1.1 deraadt * Drew D. Perkins
20 1.1 deraadt * Carnegie Mellon University
21 1.1 deraadt * 4910 Forbes Ave.
22 1.1 deraadt * Pittsburgh, PA 15213
23 1.1 deraadt * (412) 268-8576
24 1.1 deraadt * ddp (at) andrew.cmu.edu
25 1.1 deraadt *
26 1.1 deraadt * Based on:
27 1.1 deraadt * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
28 1.1 deraadt *
29 1.1 deraadt * Copyright (c) 1987 Regents of the University of California.
30 1.1 deraadt * All rights reserved.
31 1.1 deraadt *
32 1.1 deraadt * Redistribution and use in source and binary forms are permitted
33 1.1 deraadt * provided that the above copyright notice and this paragraph are
34 1.1 deraadt * duplicated in all such forms and that any documentation,
35 1.1 deraadt * advertising materials, and other materials related to such
36 1.1 deraadt * distribution and use acknowledge that the software was developed
37 1.1 deraadt * by the University of California, Berkeley. The name of the
38 1.1 deraadt * University may not be used to endorse or promote products derived
39 1.1 deraadt * from this software without specific prior written permission.
40 1.1 deraadt * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
41 1.1 deraadt * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
42 1.1 deraadt * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
43 1.1 deraadt *
44 1.1 deraadt * Serial Line interface
45 1.1 deraadt *
46 1.1 deraadt * Rick Adams
47 1.1 deraadt * Center for Seismic Studies
48 1.1 deraadt * 1300 N 17th Street, Suite 1450
49 1.1 deraadt * Arlington, Virginia 22209
50 1.1 deraadt * (703)276-7900
51 1.1 deraadt * rick (at) seismo.ARPA
52 1.1 deraadt * seismo!rick
53 1.1 deraadt *
54 1.1 deraadt * Pounded on heavily by Chris Torek (chris (at) mimsy.umd.edu, umcp-cs!chris).
55 1.1 deraadt * Converted to 4.3BSD Beta by Chris Torek.
56 1.1 deraadt * Other changes made at Berkeley, based in part on code by Kirk Smith.
57 1.1 deraadt *
58 1.1 deraadt * Converted to 4.3BSD+ 386BSD by Brad Parker (brad (at) cayman.com)
59 1.1 deraadt * Added VJ tcp header compression; more unified ioctls
60 1.1 deraadt *
61 1.1 deraadt * Extensively modified by Paul Mackerras (paulus (at) cs.anu.edu.au).
62 1.1 deraadt * Cleaned up a lot of the mbuf-related code to fix bugs that
63 1.1 deraadt * caused system crashes and packet corruption. Changed pppstart
64 1.1 deraadt * so that it doesn't just give up with a collision if the whole
65 1.1 deraadt * packet doesn't fit in the output ring buffer.
66 1.1 deraadt *
67 1.2 paulus * Added priority queueing for interactive IP packets, following
68 1.2 paulus * the model of if_sl.c, plus hooks for bpf.
69 1.2 paulus * Paul Mackerras (paulus (at) cs.anu.edu.au).
70 1.1 deraadt */
71 1.1 deraadt
72 1.12 paulus /* $Id: if_ppp.c,v 1.12 1994/06/14 03:09:23 paulus Exp $ */
73 1.2 paulus /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
74 1.2 paulus
75 1.1 deraadt #include "ppp.h"
76 1.1 deraadt #if NPPP > 0
77 1.1 deraadt
78 1.1 deraadt #define VJC
79 1.1 deraadt
80 1.5 mycroft #include <sys/param.h>
81 1.5 mycroft #include <sys/proc.h>
82 1.5 mycroft #include <sys/mbuf.h>
83 1.5 mycroft #include <sys/buf.h>
84 1.5 mycroft #include <sys/dkstat.h>
85 1.5 mycroft #include <sys/socket.h>
86 1.5 mycroft #include <sys/ioctl.h>
87 1.5 mycroft #include <sys/file.h>
88 1.5 mycroft #include <sys/tty.h>
89 1.5 mycroft #include <sys/kernel.h>
90 1.5 mycroft #include <sys/conf.h>
91 1.8 paulus #include <sys/vnode.h>
92 1.5 mycroft
93 1.5 mycroft #include <net/if.h>
94 1.5 mycroft #include <net/if_types.h>
95 1.5 mycroft #include <net/netisr.h>
96 1.5 mycroft #include <net/route.h>
97 1.5 mycroft
98 1.1 deraadt #if INET
99 1.5 mycroft #include <netinet/in.h>
100 1.5 mycroft #include <netinet/in_systm.h>
101 1.5 mycroft #include <netinet/in_var.h>
102 1.5 mycroft #include <netinet/ip.h>
103 1.1 deraadt #endif
104 1.1 deraadt
105 1.2 paulus #include "bpfilter.h"
106 1.2 paulus #if NBPFILTER > 0
107 1.5 mycroft #include <sys/time.h>
108 1.5 mycroft #include <net/bpf.h>
109 1.2 paulus #endif
110 1.2 paulus
111 1.1 deraadt #ifdef VJC
112 1.8 paulus #include <net/slcompress.h>
113 1.1 deraadt #define HDROFF MAX_HDR
114 1.1 deraadt /* HDROFF should really be 128, but other parts of the system will
115 1.1 deraadt panic on TCP+IP headers bigger than MAX_HDR = MHLEN (100). */
116 1.1 deraadt
117 1.1 deraadt #else
118 1.1 deraadt #define HDROFF (0)
119 1.1 deraadt #endif
120 1.1 deraadt
121 1.8 paulus #include <net/if_ppp.h>
122 1.6 cgd #include <machine/cpu.h>
123 1.1 deraadt
124 1.8 paulus /* This is a NetBSD-current kernel. */
125 1.8 paulus #define CCOUNT(q) ((q)->c_cc)
126 1.8 paulus
127 1.8 paulus #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
128 1.8 paulus
129 1.1 deraadt struct ppp_softc ppp_softc[NPPP];
130 1.1 deraadt
131 1.1 deraadt void pppattach __P((void));
132 1.1 deraadt int pppopen __P((dev_t dev, struct tty *tp));
133 1.1 deraadt void pppclose __P((struct tty *tp, int flag));
134 1.1 deraadt int pppread __P((struct tty *tp, struct uio *uio, int flag));
135 1.1 deraadt int pppwrite __P((struct tty *tp, struct uio *uio, int flag));
136 1.8 paulus int ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,
137 1.8 paulus struct proc *));
138 1.1 deraadt int pppoutput __P((struct ifnet *ifp, struct mbuf *m0,
139 1.9 mycroft struct sockaddr *dst, struct rtentry *rtp));
140 1.1 deraadt void pppinput __P((int c, struct tty *tp));
141 1.1 deraadt int pppioctl __P((struct ifnet *ifp, int cmd, caddr_t data));
142 1.8 paulus void pppstart __P((struct tty *tp));
143 1.1 deraadt
144 1.8 paulus static int pppasyncstart __P((struct ppp_softc *));
145 1.1 deraadt static u_short pppfcs __P((u_short fcs, u_char *cp, int len));
146 1.8 paulus static int pppgetm __P((struct ppp_softc *sc));
147 1.1 deraadt static struct mbuf *ppp_btom __P((struct ppp_softc *sc));
148 1.1 deraadt static void pppdumpm __P((struct mbuf *m0, int pktlen));
149 1.1 deraadt static void pppdumpb __P((u_char *b, int l));
150 1.8 paulus static void ppplogchar __P((struct ppp_softc *, int));
151 1.1 deraadt
152 1.1 deraadt /*
153 1.1 deraadt * Some useful mbuf macros not in mbuf.h.
154 1.1 deraadt */
155 1.1 deraadt #define M_DATASTART(m) \
156 1.1 deraadt ((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf : \
157 1.1 deraadt (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
158 1.1 deraadt
159 1.1 deraadt #define M_DATASIZE(m) \
160 1.1 deraadt ((m)->m_flags & M_EXT ? (m)->m_ext.ext_size : \
161 1.1 deraadt (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
162 1.1 deraadt
163 1.1 deraadt /*
164 1.2 paulus * The following disgusting hack gets around the problem that IP TOS
165 1.2 paulus * can't be set yet. We want to put "interactive" traffic on a high
166 1.2 paulus * priority queue. To decide if traffic is interactive, we check that
167 1.2 paulus * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
168 1.2 paulus */
169 1.2 paulus static u_short interactive_ports[8] = {
170 1.2 paulus 0, 513, 0, 0,
171 1.2 paulus 0, 21, 0, 23,
172 1.2 paulus };
173 1.2 paulus #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
174 1.2 paulus
175 1.2 paulus /*
176 1.2 paulus * Does c need to be escaped?
177 1.2 paulus */
178 1.8 paulus #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
179 1.2 paulus
180 1.2 paulus /*
181 1.1 deraadt * Called from boot code to establish ppp interfaces.
182 1.1 deraadt */
183 1.1 deraadt void
184 1.1 deraadt pppattach()
185 1.1 deraadt {
186 1.1 deraadt register struct ppp_softc *sc;
187 1.1 deraadt register int i = 0;
188 1.1 deraadt
189 1.1 deraadt for (sc = ppp_softc; i < NPPP; sc++) {
190 1.1 deraadt sc->sc_if.if_name = "ppp";
191 1.1 deraadt sc->sc_if.if_unit = i++;
192 1.1 deraadt sc->sc_if.if_mtu = PPP_MTU;
193 1.1 deraadt sc->sc_if.if_flags = IFF_POINTOPOINT;
194 1.1 deraadt sc->sc_if.if_type = IFT_PPP;
195 1.7 deraadt sc->sc_if.if_hdrlen = PPP_HDRLEN;
196 1.1 deraadt sc->sc_if.if_ioctl = pppioctl;
197 1.1 deraadt sc->sc_if.if_output = pppoutput;
198 1.1 deraadt sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
199 1.1 deraadt sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
200 1.2 paulus sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
201 1.1 deraadt if_attach(&sc->sc_if);
202 1.2 paulus #if NBPFILTER > 0
203 1.7 deraadt bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
204 1.2 paulus #endif
205 1.1 deraadt }
206 1.1 deraadt }
207 1.1 deraadt
208 1.1 deraadt /*
209 1.8 paulus * Allocate a ppp interface unit and initialize it.
210 1.8 paulus */
211 1.8 paulus struct ppp_softc *
212 1.8 paulus pppalloc(pid)
213 1.8 paulus pid_t pid;
214 1.8 paulus {
215 1.8 paulus int nppp;
216 1.8 paulus struct ppp_softc *sc;
217 1.8 paulus
218 1.8 paulus for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
219 1.8 paulus if (sc->sc_xfer == pid) {
220 1.8 paulus sc->sc_xfer = 0;
221 1.8 paulus break;
222 1.8 paulus }
223 1.8 paulus if (nppp >= NPPP)
224 1.8 paulus for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
225 1.8 paulus if (sc->sc_devp == NULL)
226 1.8 paulus break;
227 1.8 paulus if (nppp >= NPPP)
228 1.8 paulus return NULL;
229 1.8 paulus
230 1.8 paulus sc->sc_flags = 0;
231 1.8 paulus sc->sc_mru = PPP_MRU;
232 1.8 paulus #ifdef VJC
233 1.9 mycroft sl_compress_init(&sc->sc_comp, -1);
234 1.8 paulus #endif
235 1.8 paulus sc->sc_if.if_flags |= IFF_RUNNING;
236 1.8 paulus
237 1.8 paulus return sc;
238 1.8 paulus }
239 1.8 paulus
240 1.8 paulus /*
241 1.8 paulus * Deallocate a ppp unit.
242 1.8 paulus */
243 1.8 paulus pppdealloc(sc)
244 1.8 paulus struct ppp_softc *sc;
245 1.8 paulus {
246 1.8 paulus struct mbuf *m;
247 1.8 paulus
248 1.8 paulus if_down(&sc->sc_if);
249 1.8 paulus sc->sc_devp = NULL;
250 1.8 paulus sc->sc_xfer = 0;
251 1.8 paulus for (;;) {
252 1.8 paulus IF_DEQUEUE(&sc->sc_inq, m);
253 1.8 paulus if (m == NULL)
254 1.8 paulus break;
255 1.8 paulus m_freem(m);
256 1.8 paulus }
257 1.8 paulus for (;;) {
258 1.8 paulus IF_DEQUEUE(&sc->sc_fastq, m);
259 1.8 paulus if (m == NULL)
260 1.8 paulus break;
261 1.8 paulus m_freem(m);
262 1.8 paulus }
263 1.8 paulus sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
264 1.8 paulus }
265 1.8 paulus
266 1.8 paulus /*
267 1.8 paulus * Line specific open routine for async tty devices.
268 1.1 deraadt * Attach the given tty to the first available ppp unit.
269 1.1 deraadt */
270 1.1 deraadt /* ARGSUSED */
271 1.1 deraadt int
272 1.1 deraadt pppopen(dev, tp)
273 1.1 deraadt dev_t dev;
274 1.1 deraadt register struct tty *tp;
275 1.1 deraadt {
276 1.1 deraadt struct proc *p = curproc; /* XXX */
277 1.1 deraadt register struct ppp_softc *sc;
278 1.8 paulus int error, s, i;
279 1.1 deraadt
280 1.1 deraadt if (error = suser(p->p_ucred, &p->p_acflag))
281 1.1 deraadt return (error);
282 1.1 deraadt
283 1.8 paulus if (tp->t_line == PPPDISC) {
284 1.8 paulus sc = (struct ppp_softc *) tp->t_sc;
285 1.8 paulus if (sc != NULL && sc->sc_devp == (void *) tp)
286 1.8 paulus return (0);
287 1.8 paulus }
288 1.1 deraadt
289 1.8 paulus if ((sc = pppalloc(p->p_pid)) == NULL)
290 1.2 paulus return ENXIO;
291 1.2 paulus
292 1.8 paulus if (sc->sc_outm != NULL) {
293 1.8 paulus m_freem(sc->sc_outm);
294 1.8 paulus sc->sc_outm = NULL;
295 1.8 paulus }
296 1.8 paulus
297 1.8 paulus if (pppgetm(sc) == 0) {
298 1.2 paulus sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
299 1.2 paulus return (ENOBUFS);
300 1.2 paulus }
301 1.8 paulus
302 1.8 paulus sc->sc_ilen = 0;
303 1.8 paulus bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
304 1.8 paulus sc->sc_asyncmap[0] = 0xffffffff;
305 1.8 paulus sc->sc_asyncmap[3] = 0x60000000;
306 1.8 paulus sc->sc_rasyncmap = 0;
307 1.8 paulus sc->sc_devp = (void *) tp;
308 1.8 paulus sc->sc_start = pppasyncstart;
309 1.8 paulus
310 1.8 paulus tp->t_sc = (caddr_t) sc;
311 1.2 paulus ttyflush(tp, FREAD | FWRITE);
312 1.1 deraadt
313 1.2 paulus return (0);
314 1.1 deraadt }
315 1.1 deraadt
316 1.1 deraadt /*
317 1.1 deraadt * Line specific close routine.
318 1.1 deraadt * Detach the tty from the ppp unit.
319 1.1 deraadt * Mimics part of ttyclose().
320 1.1 deraadt */
321 1.1 deraadt void
322 1.1 deraadt pppclose(tp, flag)
323 1.1 deraadt struct tty *tp;
324 1.1 deraadt int flag;
325 1.1 deraadt {
326 1.1 deraadt register struct ppp_softc *sc;
327 1.1 deraadt struct mbuf *m;
328 1.1 deraadt int s;
329 1.1 deraadt
330 1.1 deraadt ttywflush(tp);
331 1.1 deraadt s = splimp(); /* paranoid; splnet probably ok */
332 1.1 deraadt tp->t_line = 0;
333 1.1 deraadt sc = (struct ppp_softc *)tp->t_sc;
334 1.1 deraadt if (sc != NULL) {
335 1.1 deraadt tp->t_sc = NULL;
336 1.8 paulus if (tp == (struct tty *) sc->sc_devp) {
337 1.8 paulus m_freem(sc->sc_outm);
338 1.8 paulus sc->sc_outm = NULL;
339 1.8 paulus m_freem(sc->sc_m);
340 1.8 paulus sc->sc_m = NULL;
341 1.8 paulus pppdealloc(sc);
342 1.1 deraadt }
343 1.1 deraadt }
344 1.1 deraadt splx(s);
345 1.1 deraadt }
346 1.1 deraadt
347 1.1 deraadt /*
348 1.1 deraadt * Line specific (tty) read routine.
349 1.1 deraadt */
350 1.1 deraadt int
351 1.1 deraadt pppread(tp, uio, flag)
352 1.1 deraadt register struct tty *tp;
353 1.1 deraadt struct uio *uio;
354 1.1 deraadt int flag;
355 1.1 deraadt {
356 1.1 deraadt register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
357 1.1 deraadt struct mbuf *m, *m0;
358 1.1 deraadt register int s;
359 1.8 paulus int error = 0;
360 1.1 deraadt
361 1.8 paulus if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
362 1.8 paulus return 0; /* end of file */
363 1.8 paulus if (sc == NULL || tp != (struct tty *) sc->sc_devp)
364 1.8 paulus return 0;
365 1.1 deraadt s = splimp();
366 1.1 deraadt while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
367 1.8 paulus if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
368 1.1 deraadt splx(s);
369 1.1 deraadt return (EWOULDBLOCK);
370 1.1 deraadt }
371 1.1 deraadt error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
372 1.12 paulus if (error) {
373 1.12 paulus splx(s);
374 1.1 deraadt return error;
375 1.12 paulus }
376 1.1 deraadt }
377 1.1 deraadt if (tp->t_line != PPPDISC) {
378 1.1 deraadt splx(s);
379 1.1 deraadt return (-1);
380 1.1 deraadt }
381 1.1 deraadt
382 1.1 deraadt /* Pull place-holder byte out of canonical queue */
383 1.1 deraadt getc(&tp->t_canq);
384 1.1 deraadt
385 1.1 deraadt /* Get the packet from the input queue */
386 1.1 deraadt IF_DEQUEUE(&sc->sc_inq, m0);
387 1.1 deraadt splx(s);
388 1.1 deraadt
389 1.1 deraadt for (m = m0; m && uio->uio_resid; m = m->m_next)
390 1.1 deraadt if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
391 1.1 deraadt break;
392 1.1 deraadt m_freem(m0);
393 1.1 deraadt return (error);
394 1.1 deraadt }
395 1.1 deraadt
396 1.1 deraadt /*
397 1.1 deraadt * Line specific (tty) write routine.
398 1.1 deraadt */
399 1.1 deraadt int
400 1.1 deraadt pppwrite(tp, uio, flag)
401 1.1 deraadt register struct tty *tp;
402 1.1 deraadt struct uio *uio;
403 1.1 deraadt int flag;
404 1.1 deraadt {
405 1.1 deraadt register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
406 1.1 deraadt struct mbuf *m, *m0, **mp;
407 1.1 deraadt struct sockaddr dst;
408 1.1 deraadt struct ppp_header *ph1, *ph2;
409 1.1 deraadt int len, error;
410 1.1 deraadt
411 1.8 paulus if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
412 1.8 paulus return 0; /* wrote 0 bytes */
413 1.1 deraadt if (tp->t_line != PPPDISC)
414 1.1 deraadt return (EINVAL);
415 1.8 paulus if (sc == NULL || tp != (struct tty *) sc->sc_devp)
416 1.8 paulus return EIO;
417 1.7 deraadt if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
418 1.7 deraadt uio->uio_resid < PPP_HDRLEN)
419 1.1 deraadt return (EMSGSIZE);
420 1.1 deraadt for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
421 1.1 deraadt MGET(m, M_WAIT, MT_DATA);
422 1.1 deraadt if ((*mp = m) == NULL) {
423 1.1 deraadt m_freem(m0);
424 1.1 deraadt return (ENOBUFS);
425 1.1 deraadt }
426 1.1 deraadt if (uio->uio_resid >= MCLBYTES / 2)
427 1.1 deraadt MCLGET(m, M_DONTWAIT);
428 1.10 cgd len = min(M_TRAILINGSPACE(m), uio->uio_resid);
429 1.1 deraadt if (error = uiomove(mtod(m, u_char *), len, uio)) {
430 1.1 deraadt m_freem(m0);
431 1.1 deraadt return (error);
432 1.1 deraadt }
433 1.1 deraadt m->m_len = len;
434 1.1 deraadt }
435 1.1 deraadt dst.sa_family = AF_UNSPEC;
436 1.1 deraadt ph1 = (struct ppp_header *) &dst.sa_data;
437 1.1 deraadt ph2 = mtod(m0, struct ppp_header *);
438 1.1 deraadt *ph1 = *ph2;
439 1.7 deraadt m0->m_data += PPP_HDRLEN;
440 1.7 deraadt m0->m_len -= PPP_HDRLEN;
441 1.9 mycroft return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
442 1.1 deraadt }
443 1.1 deraadt
444 1.1 deraadt /*
445 1.1 deraadt * Line specific (tty) ioctl routine.
446 1.1 deraadt * Provide a way to get the ppp unit number.
447 1.1 deraadt * This discipline requires that tty device drivers call
448 1.1 deraadt * the line specific l_ioctl routine from their ioctl routines.
449 1.1 deraadt */
450 1.1 deraadt /* ARGSUSED */
451 1.1 deraadt int
452 1.8 paulus ppptioctl(tp, cmd, data, flag, p)
453 1.1 deraadt struct tty *tp;
454 1.1 deraadt caddr_t data;
455 1.1 deraadt int cmd, flag;
456 1.8 paulus struct proc *p;
457 1.1 deraadt {
458 1.8 paulus register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
459 1.2 paulus int s, error, flags, mru;
460 1.1 deraadt
461 1.8 paulus if (sc == NULL || tp != (struct tty *) sc->sc_devp)
462 1.8 paulus return -1;
463 1.8 paulus
464 1.1 deraadt switch (cmd) {
465 1.1 deraadt case FIONREAD:
466 1.1 deraadt *(int *)data = sc->sc_inq.ifq_len;
467 1.1 deraadt break;
468 1.1 deraadt
469 1.1 deraadt case PPPIOCGUNIT:
470 1.1 deraadt *(int *)data = sc->sc_if.if_unit;
471 1.1 deraadt break;
472 1.1 deraadt
473 1.1 deraadt case PPPIOCGFLAGS:
474 1.1 deraadt *(u_int *)data = sc->sc_flags;
475 1.1 deraadt break;
476 1.1 deraadt
477 1.1 deraadt case PPPIOCSFLAGS:
478 1.1 deraadt if (error = suser(p->p_ucred, &p->p_acflag))
479 1.1 deraadt return (error);
480 1.2 paulus flags = *(int *)data & SC_MASK;
481 1.1 deraadt s = splimp();
482 1.2 paulus sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
483 1.1 deraadt splx(s);
484 1.1 deraadt break;
485 1.1 deraadt
486 1.1 deraadt case PPPIOCSASYNCMAP:
487 1.1 deraadt if (error = suser(p->p_ucred, &p->p_acflag))
488 1.1 deraadt return (error);
489 1.8 paulus sc->sc_asyncmap[0] = *(u_int *)data;
490 1.1 deraadt break;
491 1.1 deraadt
492 1.1 deraadt case PPPIOCGASYNCMAP:
493 1.8 paulus *(u_int *)data = sc->sc_asyncmap[0];
494 1.1 deraadt break;
495 1.1 deraadt
496 1.2 paulus case PPPIOCSRASYNCMAP:
497 1.2 paulus if (error = suser(p->p_ucred, &p->p_acflag))
498 1.2 paulus return (error);
499 1.2 paulus sc->sc_rasyncmap = *(u_int *)data;
500 1.2 paulus break;
501 1.2 paulus
502 1.2 paulus case PPPIOCGRASYNCMAP:
503 1.2 paulus *(u_int *)data = sc->sc_rasyncmap;
504 1.2 paulus break;
505 1.2 paulus
506 1.8 paulus case PPPIOCSXASYNCMAP:
507 1.8 paulus if (error = suser(p->p_ucred, &p->p_acflag))
508 1.8 paulus return (error);
509 1.8 paulus bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
510 1.8 paulus sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
511 1.8 paulus sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
512 1.8 paulus sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
513 1.8 paulus break;
514 1.8 paulus
515 1.8 paulus case PPPIOCGXASYNCMAP:
516 1.8 paulus bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
517 1.8 paulus break;
518 1.8 paulus
519 1.2 paulus case PPPIOCSMRU:
520 1.2 paulus if (error = suser(p->p_ucred, &p->p_acflag))
521 1.2 paulus return (error);
522 1.2 paulus mru = *(int *)data;
523 1.2 paulus if (mru >= PPP_MRU && mru <= PPP_MAXMRU) {
524 1.2 paulus sc->sc_mru = mru;
525 1.8 paulus if (pppgetm(sc) == 0) {
526 1.2 paulus error = ENOBUFS;
527 1.2 paulus sc->sc_mru = PPP_MRU;
528 1.8 paulus if (pppgetm(sc) == 0)
529 1.2 paulus sc->sc_if.if_flags &= ~IFF_UP;
530 1.2 paulus }
531 1.2 paulus }
532 1.2 paulus break;
533 1.2 paulus
534 1.2 paulus case PPPIOCGMRU:
535 1.2 paulus *(int *)data = sc->sc_mru;
536 1.2 paulus break;
537 1.2 paulus
538 1.8 paulus #ifdef VJC
539 1.8 paulus case PPPIOCSMAXCID:
540 1.8 paulus if (error = suser(p->p_ucred, &p->p_acflag))
541 1.8 paulus return (error);
542 1.9 mycroft sl_compress_init(&sc->sc_comp, *(int *)data);
543 1.8 paulus break;
544 1.8 paulus #endif
545 1.8 paulus
546 1.8 paulus case PPPIOCXFERUNIT:
547 1.8 paulus if (error = suser(p->p_ucred, &p->p_acflag))
548 1.8 paulus return (error);
549 1.8 paulus sc->sc_xfer = p->p_pid;
550 1.8 paulus break;
551 1.8 paulus
552 1.1 deraadt default:
553 1.1 deraadt return (-1);
554 1.1 deraadt }
555 1.1 deraadt return (0);
556 1.1 deraadt }
557 1.1 deraadt
558 1.1 deraadt /*
559 1.1 deraadt * FCS lookup table as calculated by genfcstab.
560 1.1 deraadt */
561 1.1 deraadt static u_short fcstab[256] = {
562 1.1 deraadt 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
563 1.1 deraadt 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
564 1.1 deraadt 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
565 1.1 deraadt 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
566 1.1 deraadt 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
567 1.1 deraadt 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
568 1.1 deraadt 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
569 1.1 deraadt 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
570 1.1 deraadt 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
571 1.1 deraadt 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
572 1.1 deraadt 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
573 1.1 deraadt 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
574 1.1 deraadt 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
575 1.1 deraadt 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
576 1.1 deraadt 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
577 1.1 deraadt 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
578 1.1 deraadt 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
579 1.1 deraadt 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
580 1.1 deraadt 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
581 1.1 deraadt 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
582 1.1 deraadt 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
583 1.1 deraadt 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
584 1.1 deraadt 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
585 1.1 deraadt 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
586 1.1 deraadt 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
587 1.1 deraadt 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
588 1.1 deraadt 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
589 1.1 deraadt 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
590 1.1 deraadt 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
591 1.1 deraadt 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
592 1.1 deraadt 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
593 1.1 deraadt 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
594 1.1 deraadt };
595 1.1 deraadt
596 1.1 deraadt /*
597 1.1 deraadt * Calculate a new FCS given the current FCS and the new data.
598 1.1 deraadt */
599 1.1 deraadt static u_short
600 1.1 deraadt pppfcs(fcs, cp, len)
601 1.1 deraadt register u_short fcs;
602 1.1 deraadt register u_char *cp;
603 1.1 deraadt register int len;
604 1.1 deraadt {
605 1.1 deraadt while (len--)
606 1.1 deraadt fcs = PPP_FCS(fcs, *cp++);
607 1.1 deraadt return (fcs);
608 1.1 deraadt }
609 1.1 deraadt
610 1.1 deraadt /*
611 1.1 deraadt * Queue a packet. Start transmission if not active.
612 1.1 deraadt * Packet is placed in Information field of PPP frame.
613 1.1 deraadt */
614 1.1 deraadt int
615 1.9 mycroft pppoutput(ifp, m0, dst, rtp)
616 1.1 deraadt struct ifnet *ifp;
617 1.1 deraadt struct mbuf *m0;
618 1.1 deraadt struct sockaddr *dst;
619 1.9 mycroft struct rtentry *rtp;
620 1.1 deraadt {
621 1.1 deraadt register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
622 1.1 deraadt struct ppp_header *ph;
623 1.2 paulus int protocol, address, control;
624 1.2 paulus u_char *cp;
625 1.2 paulus int s, error;
626 1.2 paulus struct ip *ip;
627 1.2 paulus struct ifqueue *ifq;
628 1.1 deraadt
629 1.8 paulus if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
630 1.1 deraadt || (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) {
631 1.1 deraadt error = ENETDOWN; /* sort of */
632 1.1 deraadt goto bad;
633 1.1 deraadt }
634 1.1 deraadt
635 1.1 deraadt /*
636 1.1 deraadt * Compute PPP header.
637 1.1 deraadt */
638 1.1 deraadt address = PPP_ALLSTATIONS;
639 1.1 deraadt control = PPP_UI;
640 1.2 paulus ifq = &ifp->if_snd;
641 1.1 deraadt switch (dst->sa_family) {
642 1.1 deraadt #ifdef INET
643 1.1 deraadt case AF_INET:
644 1.1 deraadt protocol = PPP_IP;
645 1.8 paulus if ((sc->sc_flags & SC_ENABLE_IP) == 0) {
646 1.8 paulus error = ENETDOWN;
647 1.8 paulus goto bad;
648 1.8 paulus }
649 1.8 paulus
650 1.2 paulus /*
651 1.2 paulus * If this is a TCP packet to or from an "interactive" port,
652 1.2 paulus * put the packet on the fastq instead.
653 1.2 paulus */
654 1.2 paulus if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {
655 1.8 paulus register int p = ntohl(((int *)ip)[ip->ip_hl]);
656 1.2 paulus if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))
657 1.2 paulus ifq = &sc->sc_fastq;
658 1.1 deraadt }
659 1.1 deraadt break;
660 1.1 deraadt #endif
661 1.1 deraadt #ifdef NS
662 1.1 deraadt case AF_NS:
663 1.1 deraadt protocol = PPP_XNS;
664 1.1 deraadt break;
665 1.1 deraadt #endif
666 1.1 deraadt case AF_UNSPEC:
667 1.1 deraadt ph = (struct ppp_header *) dst->sa_data;
668 1.1 deraadt address = ph->ph_address;
669 1.1 deraadt control = ph->ph_control;
670 1.1 deraadt protocol = ntohs(ph->ph_protocol);
671 1.1 deraadt break;
672 1.1 deraadt default:
673 1.1 deraadt printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
674 1.1 deraadt error = EAFNOSUPPORT;
675 1.1 deraadt goto bad;
676 1.1 deraadt }
677 1.1 deraadt
678 1.1 deraadt /*
679 1.1 deraadt * Add PPP header. If no space in first mbuf, allocate another.
680 1.2 paulus * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
681 1.1 deraadt */
682 1.7 deraadt if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
683 1.7 deraadt m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
684 1.1 deraadt if (m0 == 0) {
685 1.1 deraadt error = ENOBUFS;
686 1.1 deraadt goto bad;
687 1.1 deraadt }
688 1.1 deraadt m0->m_len = 0;
689 1.1 deraadt } else
690 1.7 deraadt m0->m_data -= PPP_HDRLEN;
691 1.1 deraadt
692 1.1 deraadt cp = mtod(m0, u_char *);
693 1.2 paulus *cp++ = address;
694 1.2 paulus *cp++ = control;
695 1.2 paulus *cp++ = protocol >> 8;
696 1.1 deraadt *cp++ = protocol & 0xff;
697 1.7 deraadt m0->m_len += PPP_HDRLEN;
698 1.1 deraadt
699 1.8 paulus if (sc->sc_flags & SC_LOG_OUTPKT) {
700 1.1 deraadt printf("ppp%d output: ", ifp->if_unit);
701 1.1 deraadt pppdumpm(m0, -1);
702 1.1 deraadt }
703 1.1 deraadt
704 1.2 paulus #if NBPFILTER > 0
705 1.2 paulus /* See if bpf wants to look at the packet. */
706 1.2 paulus if (sc->sc_bpf)
707 1.2 paulus bpf_mtap(sc->sc_bpf, m0);
708 1.2 paulus #endif
709 1.2 paulus
710 1.2 paulus /*
711 1.2 paulus * Put the packet on the appropriate queue.
712 1.2 paulus */
713 1.1 deraadt s = splimp();
714 1.2 paulus if (IF_QFULL(ifq)) {
715 1.2 paulus IF_DROP(ifq);
716 1.1 deraadt splx(s);
717 1.1 deraadt sc->sc_if.if_oerrors++;
718 1.1 deraadt error = ENOBUFS;
719 1.1 deraadt goto bad;
720 1.1 deraadt }
721 1.2 paulus IF_ENQUEUE(ifq, m0);
722 1.8 paulus
723 1.4 paulus /*
724 1.8 paulus * Tell the device to send it out.
725 1.4 paulus */
726 1.8 paulus (*sc->sc_start)(sc);
727 1.8 paulus
728 1.1 deraadt splx(s);
729 1.1 deraadt return (0);
730 1.1 deraadt
731 1.1 deraadt bad:
732 1.1 deraadt m_freem(m0);
733 1.1 deraadt return (error);
734 1.1 deraadt }
735 1.1 deraadt
736 1.1 deraadt /*
737 1.8 paulus * Grab another packet off a queue and apply VJ compression,
738 1.8 paulus * address/control and/or protocol compression if appropriate.
739 1.8 paulus */
740 1.8 paulus struct mbuf *
741 1.8 paulus ppp_dequeue(sc)
742 1.8 paulus struct ppp_softc *sc;
743 1.8 paulus {
744 1.8 paulus int s;
745 1.8 paulus struct mbuf *m;
746 1.8 paulus u_char *cp;
747 1.8 paulus int address, control, protocol;
748 1.8 paulus
749 1.8 paulus s = splimp();
750 1.8 paulus IF_DEQUEUE(&sc->sc_fastq, m);
751 1.8 paulus if (m == NULL)
752 1.8 paulus IF_DEQUEUE(&sc->sc_if.if_snd, m);
753 1.8 paulus splx(s);
754 1.8 paulus if (m == NULL)
755 1.8 paulus return NULL;
756 1.8 paulus
757 1.8 paulus /*
758 1.8 paulus * Extract the ppp header of the new packet.
759 1.8 paulus * The ppp header will be in one mbuf.
760 1.8 paulus */
761 1.8 paulus cp = mtod(m, u_char *);
762 1.8 paulus address = cp[0];
763 1.8 paulus control = cp[1];
764 1.8 paulus protocol = (cp[2] << 8) + cp[3];
765 1.8 paulus
766 1.8 paulus #ifdef VJC
767 1.8 paulus /*
768 1.8 paulus * If the packet is a TCP/IP packet, see if we can compress it.
769 1.8 paulus */
770 1.8 paulus if (protocol == PPP_IP && sc->sc_flags & SC_COMP_TCP) {
771 1.8 paulus struct ip *ip;
772 1.8 paulus int type;
773 1.8 paulus struct mbuf *mp;
774 1.8 paulus
775 1.8 paulus mp = m;
776 1.8 paulus ip = (struct ip *) (cp + PPP_HDRLEN);
777 1.8 paulus if (mp->m_len <= PPP_HDRLEN) {
778 1.8 paulus mp = mp->m_next;
779 1.8 paulus ip = mtod(mp, struct ip *);
780 1.8 paulus }
781 1.8 paulus /* this code assumes the IP/TCP header is in one non-shared mbuf */
782 1.8 paulus if (ip->ip_p == IPPROTO_TCP) {
783 1.8 paulus type = sl_compress_tcp(mp, ip, &sc->sc_comp,
784 1.8 paulus !(sc->sc_flags & SC_NO_TCP_CCID));
785 1.8 paulus switch (type) {
786 1.8 paulus case TYPE_UNCOMPRESSED_TCP:
787 1.8 paulus protocol = PPP_VJC_UNCOMP;
788 1.8 paulus break;
789 1.8 paulus case TYPE_COMPRESSED_TCP:
790 1.8 paulus protocol = PPP_VJC_COMP;
791 1.8 paulus cp = mtod(m, u_char *);
792 1.8 paulus cp[0] = address; /* header has moved */
793 1.8 paulus cp[1] = control;
794 1.8 paulus cp[2] = 0;
795 1.8 paulus break;
796 1.8 paulus }
797 1.8 paulus cp[3] = protocol; /* update protocol in PPP header */
798 1.8 paulus }
799 1.8 paulus }
800 1.8 paulus #endif /* VJC */
801 1.8 paulus
802 1.8 paulus #ifdef BSD_COMP
803 1.8 paulus if (protocol < PPP_COMP && (sc->sc_flags & SC_BSD_COMP)) {
804 1.8 paulus slen = m_totallen(m0);
805 1.8 paulus clen = pf_bsd_comp(sc->sc_bsd_db, cbuf, proto, m0, slen);
806 1.8 paulus }
807 1.8 paulus #endif /* BSD_COMP */
808 1.8 paulus
809 1.8 paulus /*
810 1.8 paulus * Compress the address/control and protocol, if possible.
811 1.8 paulus */
812 1.8 paulus if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
813 1.8 paulus control == PPP_UI && protocol != PPP_ALLSTATIONS &&
814 1.8 paulus protocol != PPP_LCP) {
815 1.8 paulus /* can compress address/control */
816 1.8 paulus m->m_data += 2;
817 1.8 paulus m->m_len -= 2;
818 1.8 paulus }
819 1.8 paulus if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
820 1.8 paulus /* can compress protocol */
821 1.8 paulus if (mtod(m, u_char *) == cp) {
822 1.8 paulus cp[2] = cp[1]; /* move address/control up */
823 1.8 paulus cp[1] = cp[0];
824 1.8 paulus }
825 1.8 paulus ++m->m_data;
826 1.8 paulus --m->m_len;
827 1.8 paulus }
828 1.8 paulus
829 1.8 paulus return m;
830 1.8 paulus }
831 1.8 paulus
832 1.8 paulus /*
833 1.8 paulus * This gets called from pppoutput when a new packet is
834 1.8 paulus * put on a queue.
835 1.8 paulus */
836 1.8 paulus static
837 1.8 paulus pppasyncstart(sc)
838 1.8 paulus register struct ppp_softc *sc;
839 1.8 paulus {
840 1.8 paulus register struct tty *tp = (struct tty *) sc->sc_devp;
841 1.8 paulus
842 1.8 paulus pppstart(tp);
843 1.8 paulus }
844 1.8 paulus
845 1.8 paulus /*
846 1.8 paulus * Start output on async tty interface. Get another datagram
847 1.8 paulus * to send from the interface queue and start sending it.
848 1.1 deraadt */
849 1.1 deraadt void
850 1.1 deraadt pppstart(tp)
851 1.1 deraadt register struct tty *tp;
852 1.1 deraadt {
853 1.8 paulus register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
854 1.1 deraadt register struct mbuf *m;
855 1.1 deraadt register int len;
856 1.1 deraadt register u_char *start, *stop, *cp;
857 1.2 paulus int n, s, ndone, done;
858 1.1 deraadt struct mbuf *m2;
859 1.8 paulus
860 1.8 paulus if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
861 1.8 paulus /* sorry, I can't talk now */
862 1.8 paulus return;
863 1.8 paulus }
864 1.8 paulus if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
865 1.8 paulus (*tp->t_oproc)(tp);
866 1.8 paulus return;
867 1.8 paulus }
868 1.1 deraadt
869 1.1 deraadt for (;;) {
870 1.1 deraadt /*
871 1.1 deraadt * If there is more in the output queue, just send it now.
872 1.1 deraadt * We are being called in lieu of ttstart and must do what
873 1.1 deraadt * it would.
874 1.1 deraadt */
875 1.1 deraadt if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
876 1.1 deraadt (*tp->t_oproc)(tp);
877 1.1 deraadt if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
878 1.1 deraadt return;
879 1.1 deraadt }
880 1.1 deraadt
881 1.1 deraadt /*
882 1.1 deraadt * See if we have an existing packet partly sent.
883 1.1 deraadt * If not, get a new packet and start sending it.
884 1.2 paulus * We take packets on the priority queue ahead of those
885 1.2 paulus * on the normal queue.
886 1.1 deraadt */
887 1.1 deraadt m = sc->sc_outm;
888 1.1 deraadt if (m == NULL) {
889 1.8 paulus /*
890 1.8 paulus * Get another packet to be sent
891 1.8 paulus */
892 1.8 paulus m = ppp_dequeue(sc);
893 1.1 deraadt if (m == NULL)
894 1.1 deraadt return;
895 1.1 deraadt
896 1.1 deraadt /*
897 1.1 deraadt * The extra PPP_FLAG will start up a new packet, and thus
898 1.1 deraadt * will flush any accumulated garbage. We do this whenever
899 1.1 deraadt * the line may have been idle for some time.
900 1.1 deraadt */
901 1.1 deraadt if (CCOUNT(&tp->t_outq) == 0) {
902 1.1 deraadt ++sc->sc_bytessent;
903 1.1 deraadt (void) putc(PPP_FLAG, &tp->t_outq);
904 1.1 deraadt }
905 1.2 paulus
906 1.2 paulus /* Calculate the FCS for the first mbuf's worth. */
907 1.2 paulus sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
908 1.1 deraadt }
909 1.1 deraadt
910 1.2 paulus for (;;) {
911 1.1 deraadt start = mtod(m, u_char *);
912 1.1 deraadt len = m->m_len;
913 1.1 deraadt stop = start + len;
914 1.1 deraadt while (len > 0) {
915 1.1 deraadt /*
916 1.1 deraadt * Find out how many bytes in the string we can
917 1.1 deraadt * handle without doing something special.
918 1.1 deraadt */
919 1.1 deraadt for (cp = start; cp < stop; cp++)
920 1.2 paulus if (ESCAPE_P(*cp))
921 1.1 deraadt break;
922 1.1 deraadt n = cp - start;
923 1.1 deraadt if (n) {
924 1.1 deraadt #ifndef RB_LEN
925 1.2 paulus /* NetBSD (0.9 or later), 4.3-Reno or similar. */
926 1.1 deraadt ndone = n - b_to_q(start, n, &tp->t_outq);
927 1.1 deraadt #else
928 1.2 paulus #ifdef NetBSD
929 1.4 paulus /* NetBSD with 2-byte ring buffer entries */
930 1.2 paulus ndone = rb_cwrite(&tp->t_out, start, n);
931 1.2 paulus #else
932 1.4 paulus /* 386BSD, FreeBSD */
933 1.1 deraadt int cc, nleft;
934 1.1 deraadt for (nleft = n; nleft > 0; nleft -= cc) {
935 1.1 deraadt if ((cc = RB_CONTIGPUT(&tp->t_out)) == 0)
936 1.1 deraadt break;
937 1.1 deraadt cc = min (cc, nleft);
938 1.4 paulus bcopy((char *)start + n - nleft, tp->t_out.rb_tl, cc);
939 1.1 deraadt tp->t_out.rb_tl = RB_ROLLOVER(&tp->t_out,
940 1.1 deraadt tp->t_out.rb_tl + cc);
941 1.1 deraadt }
942 1.1 deraadt ndone = n - nleft;
943 1.2 paulus #endif /* NetBSD */
944 1.1 deraadt #endif /* RB_LEN */
945 1.1 deraadt len -= ndone;
946 1.1 deraadt start += ndone;
947 1.1 deraadt sc->sc_bytessent += ndone;
948 1.1 deraadt
949 1.1 deraadt if (ndone < n)
950 1.1 deraadt break; /* packet doesn't fit */
951 1.1 deraadt }
952 1.1 deraadt /*
953 1.1 deraadt * If there are characters left in the mbuf,
954 1.1 deraadt * the first one must be special..
955 1.1 deraadt * Put it out in a different form.
956 1.1 deraadt */
957 1.1 deraadt if (len) {
958 1.1 deraadt if (putc(PPP_ESCAPE, &tp->t_outq))
959 1.1 deraadt break;
960 1.1 deraadt if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
961 1.1 deraadt (void) unputc(&tp->t_outq);
962 1.1 deraadt break;
963 1.1 deraadt }
964 1.1 deraadt sc->sc_bytessent += 2;
965 1.1 deraadt start++;
966 1.1 deraadt len--;
967 1.1 deraadt }
968 1.1 deraadt }
969 1.1 deraadt /*
970 1.1 deraadt * If we didn't empty this mbuf, remember where we're up to.
971 1.2 paulus * If we emptied the last mbuf, try to add the FCS and closing
972 1.2 paulus * flag, and if we can't, leave sc_outm pointing to m, but with
973 1.2 paulus * m->m_len == 0, to remind us to output the FCS and flag later.
974 1.1 deraadt */
975 1.2 paulus done = len == 0;
976 1.2 paulus if (done && m->m_next == NULL) {
977 1.2 paulus u_char *p, *q;
978 1.2 paulus int c;
979 1.2 paulus u_char endseq[8];
980 1.2 paulus
981 1.2 paulus /*
982 1.2 paulus * We may have to escape the bytes in the FCS.
983 1.2 paulus */
984 1.2 paulus p = endseq;
985 1.2 paulus c = ~sc->sc_outfcs & 0xFF;
986 1.2 paulus if (ESCAPE_P(c)) {
987 1.2 paulus *p++ = PPP_ESCAPE;
988 1.2 paulus *p++ = c ^ PPP_TRANS;
989 1.2 paulus } else
990 1.2 paulus *p++ = c;
991 1.2 paulus c = (~sc->sc_outfcs >> 8) & 0xFF;
992 1.2 paulus if (ESCAPE_P(c)) {
993 1.2 paulus *p++ = PPP_ESCAPE;
994 1.2 paulus *p++ = c ^ PPP_TRANS;
995 1.2 paulus } else
996 1.2 paulus *p++ = c;
997 1.2 paulus *p++ = PPP_FLAG;
998 1.2 paulus
999 1.2 paulus /*
1000 1.2 paulus * Try to output the FCS and flag. If the bytes
1001 1.2 paulus * don't all fit, back out.
1002 1.2 paulus */
1003 1.2 paulus for (q = endseq; q < p; ++q)
1004 1.2 paulus if (putc(*q, &tp->t_outq)) {
1005 1.2 paulus done = 0;
1006 1.2 paulus for (; q > endseq; --q)
1007 1.2 paulus unputc(&tp->t_outq);
1008 1.2 paulus break;
1009 1.2 paulus }
1010 1.2 paulus }
1011 1.2 paulus
1012 1.2 paulus if (!done) {
1013 1.1 deraadt m->m_data = start;
1014 1.1 deraadt m->m_len = len;
1015 1.1 deraadt sc->sc_outm = m;
1016 1.1 deraadt if (tp->t_oproc != NULL)
1017 1.1 deraadt (*tp->t_oproc)(tp);
1018 1.1 deraadt return; /* can't do any more at the moment */
1019 1.1 deraadt }
1020 1.1 deraadt
1021 1.1 deraadt /* Finished with this mbuf; free it and move on. */
1022 1.1 deraadt MFREE(m, m2);
1023 1.2 paulus if (m2 == NULL)
1024 1.2 paulus break;
1025 1.2 paulus
1026 1.1 deraadt m = m2;
1027 1.2 paulus sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
1028 1.2 paulus }
1029 1.1 deraadt
1030 1.1 deraadt /* Finished a packet */
1031 1.1 deraadt sc->sc_outm = NULL;
1032 1.1 deraadt sc->sc_bytessent++; /* account for closing flag */
1033 1.1 deraadt sc->sc_if.if_opackets++;
1034 1.1 deraadt sc->sc_if.if_obytes = sc->sc_bytessent;
1035 1.1 deraadt }
1036 1.1 deraadt }
1037 1.1 deraadt
1038 1.1 deraadt /*
1039 1.2 paulus * Allocate enough mbuf to handle current MRU.
1040 1.1 deraadt */
1041 1.1 deraadt static int
1042 1.8 paulus pppgetm(sc)
1043 1.1 deraadt register struct ppp_softc *sc;
1044 1.1 deraadt {
1045 1.1 deraadt struct mbuf *m, **mp;
1046 1.8 paulus int len = HDROFF + sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN;
1047 1.1 deraadt int s;
1048 1.1 deraadt
1049 1.1 deraadt s = splimp();
1050 1.1 deraadt for (mp = &sc->sc_m; (m = *mp) != NULL; mp = &m->m_next)
1051 1.1 deraadt if ((len -= M_DATASIZE(m)) <= 0) {
1052 1.1 deraadt splx(s);
1053 1.1 deraadt return (1);
1054 1.1 deraadt }
1055 1.1 deraadt
1056 1.1 deraadt for (;; mp = &m->m_next) {
1057 1.1 deraadt MGETHDR(m, M_DONTWAIT, MT_DATA);
1058 1.1 deraadt if (m == 0) {
1059 1.1 deraadt m_freem(sc->sc_m);
1060 1.1 deraadt sc->sc_m = NULL;
1061 1.1 deraadt splx(s);
1062 1.2 paulus printf("ppp%d: can't allocate mbuf\n", sc->sc_if.if_unit);
1063 1.1 deraadt return (0);
1064 1.1 deraadt }
1065 1.1 deraadt *mp = m;
1066 1.1 deraadt MCLGET(m, M_DONTWAIT);
1067 1.1 deraadt if ((len -= M_DATASIZE(m)) <= 0) {
1068 1.1 deraadt splx(s);
1069 1.1 deraadt return (1);
1070 1.1 deraadt }
1071 1.1 deraadt }
1072 1.1 deraadt }
1073 1.1 deraadt
1074 1.1 deraadt /*
1075 1.1 deraadt * Copy mbuf chain. Would like to use m_copy(), but we need a real copy
1076 1.1 deraadt * of the data, not just copies of pointers to the data.
1077 1.1 deraadt */
1078 1.1 deraadt static struct mbuf *
1079 1.1 deraadt ppp_btom(sc)
1080 1.1 deraadt struct ppp_softc *sc;
1081 1.1 deraadt {
1082 1.1 deraadt register struct mbuf *m, **mp;
1083 1.1 deraadt struct mbuf *top = sc->sc_m;
1084 1.1 deraadt
1085 1.1 deraadt /*
1086 1.1 deraadt * First check current mbuf. If we have more than a small mbuf,
1087 1.1 deraadt * return the whole cluster and set beginning of buffer to the
1088 1.1 deraadt * next mbuf.
1089 1.1 deraadt * Else, copy the current bytes into a small mbuf, attach the new
1090 1.1 deraadt * mbuf to the end of the chain and set beginning of buffer to the
1091 1.1 deraadt * current mbuf.
1092 1.1 deraadt */
1093 1.1 deraadt
1094 1.1 deraadt if (sc->sc_mc->m_len > MHLEN) {
1095 1.1 deraadt sc->sc_m = sc->sc_mc->m_next;
1096 1.1 deraadt sc->sc_mc->m_next = NULL;
1097 1.1 deraadt }
1098 1.1 deraadt else {
1099 1.1 deraadt /* rather than waste a whole cluster on <= MHLEN bytes,
1100 1.1 deraadt alloc a small mbuf and copy to it */
1101 1.1 deraadt MGETHDR(m, M_DONTWAIT, MT_DATA);
1102 1.1 deraadt if (m == NULL)
1103 1.1 deraadt return (NULL);
1104 1.1 deraadt
1105 1.2 paulus bcopy(mtod(sc->sc_mc, caddr_t), mtod(m, caddr_t), sc->sc_mc->m_len);
1106 1.1 deraadt m->m_len = sc->sc_mc->m_len;
1107 1.1 deraadt for (mp = ⊤ *mp != sc->sc_mc; mp = &(*mp)->m_next)
1108 1.1 deraadt ;
1109 1.1 deraadt *mp = m;
1110 1.1 deraadt sc->sc_m = sc->sc_mc;
1111 1.1 deraadt }
1112 1.1 deraadt
1113 1.1 deraadt /*
1114 1.1 deraadt * Try to allocate enough extra mbufs to handle the next packet.
1115 1.1 deraadt */
1116 1.8 paulus if (pppgetm(sc) == 0) {
1117 1.1 deraadt m_freem(top);
1118 1.8 paulus if (pppgetm(sc) == 0)
1119 1.1 deraadt sc->sc_if.if_flags &= ~IFF_UP;
1120 1.1 deraadt return (NULL);
1121 1.1 deraadt }
1122 1.1 deraadt
1123 1.1 deraadt return (top);
1124 1.1 deraadt }
1125 1.1 deraadt
1126 1.1 deraadt /*
1127 1.8 paulus * PPP packet input routine.
1128 1.8 paulus * The caller has checked and removed the FCS.
1129 1.8 paulus * The return value is 1 if the packet was put on sc->sc_inq,
1130 1.8 paulus * 0 otherwise.
1131 1.1 deraadt */
1132 1.1 deraadt #define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
1133 1.1 deraadt TYPE_UNCOMPRESSED_TCP)
1134 1.1 deraadt
1135 1.8 paulus int
1136 1.8 paulus ppppktin(sc, m, ilen)
1137 1.8 paulus struct ppp_softc *sc;
1138 1.8 paulus struct mbuf *m;
1139 1.8 paulus int ilen;
1140 1.8 paulus {
1141 1.8 paulus struct ifqueue *inq;
1142 1.8 paulus int s, xlen, proto, rv;
1143 1.8 paulus struct ppp_header hdr;
1144 1.8 paulus
1145 1.8 paulus sc->sc_if.if_ipackets++;
1146 1.8 paulus rv = 0;
1147 1.8 paulus
1148 1.8 paulus hdr = *mtod(m, struct ppp_header *);
1149 1.8 paulus proto = ntohs(hdr.ph_protocol);
1150 1.8 paulus
1151 1.8 paulus #ifdef VJC
1152 1.8 paulus /*
1153 1.8 paulus * See if we have a VJ-compressed packet to uncompress.
1154 1.8 paulus */
1155 1.8 paulus if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
1156 1.8 paulus char *pkttype = proto == PPP_VJC_COMP? "": "un";
1157 1.8 paulus
1158 1.8 paulus if (sc->sc_flags & SC_REJ_COMP_TCP) {
1159 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1160 1.8 paulus printf("ppp%d: %scomp pkt w/o compression; flags 0x%x\n",
1161 1.8 paulus sc->sc_if.if_unit, pkttype, sc->sc_flags);
1162 1.8 paulus sc->sc_if.if_ierrors++;
1163 1.8 paulus return 0;
1164 1.8 paulus }
1165 1.8 paulus
1166 1.8 paulus m->m_data += PPP_HDRLEN;
1167 1.8 paulus m->m_len -= PPP_HDRLEN;
1168 1.8 paulus ilen -= PPP_HDRLEN;
1169 1.8 paulus xlen = sl_uncompress_tcp_part((u_char **)(&m->m_data),
1170 1.8 paulus m->m_len, ilen,
1171 1.8 paulus COMPTYPE(proto), &sc->sc_comp);
1172 1.8 paulus
1173 1.8 paulus if (xlen == 0) {
1174 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1175 1.8 paulus printf("ppp%d: sl_uncompress failed on type %scomp\n",
1176 1.8 paulus sc->sc_if.if_unit, pkttype);
1177 1.8 paulus sc->sc_if.if_ierrors++;
1178 1.8 paulus return 0;
1179 1.8 paulus }
1180 1.8 paulus
1181 1.8 paulus /* adjust the first mbuf by the decompressed amt */
1182 1.8 paulus xlen += PPP_HDRLEN;
1183 1.8 paulus m->m_len += xlen - ilen;
1184 1.8 paulus ilen = xlen;
1185 1.8 paulus m->m_data -= PPP_HDRLEN;
1186 1.8 paulus proto = PPP_IP;
1187 1.8 paulus
1188 1.8 paulus /* put the ppp header back in place */
1189 1.8 paulus hdr.ph_protocol = htons(PPP_IP);
1190 1.8 paulus *mtod(m, struct ppp_header *) = hdr;
1191 1.8 paulus }
1192 1.8 paulus #endif /* VJC */
1193 1.8 paulus
1194 1.8 paulus /* get this packet as an mbuf chain */
1195 1.8 paulus if ((m = ppp_btom(sc)) == NULL) {
1196 1.8 paulus sc->sc_if.if_ierrors++;
1197 1.8 paulus return 0;
1198 1.8 paulus }
1199 1.8 paulus m->m_pkthdr.len = ilen;
1200 1.8 paulus m->m_pkthdr.rcvif = &sc->sc_if;
1201 1.8 paulus
1202 1.8 paulus #if NBPFILTER > 0
1203 1.8 paulus /* See if bpf wants to look at the packet. */
1204 1.8 paulus if (sc->sc_bpf)
1205 1.8 paulus bpf_mtap(sc->sc_bpf, m);
1206 1.8 paulus #endif
1207 1.8 paulus
1208 1.8 paulus switch (proto) {
1209 1.8 paulus #ifdef INET
1210 1.8 paulus case PPP_IP:
1211 1.8 paulus /*
1212 1.8 paulus * IP packet - take off the ppp header and pass it up to IP.
1213 1.8 paulus */
1214 1.8 paulus if ((sc->sc_if.if_flags & IFF_UP) == 0
1215 1.8 paulus || (sc->sc_flags & SC_ENABLE_IP) == 0) {
1216 1.8 paulus /* interface is down - drop the packet. */
1217 1.8 paulus m_freem(m);
1218 1.8 paulus return 0;
1219 1.8 paulus }
1220 1.8 paulus m->m_pkthdr.len -= PPP_HDRLEN;
1221 1.8 paulus m->m_data += PPP_HDRLEN;
1222 1.8 paulus m->m_len -= PPP_HDRLEN;
1223 1.8 paulus schednetisr(NETISR_IP);
1224 1.8 paulus inq = &ipintrq;
1225 1.8 paulus break;
1226 1.8 paulus #endif
1227 1.8 paulus
1228 1.8 paulus default:
1229 1.8 paulus /*
1230 1.8 paulus * Some other protocol - place on input queue for read().
1231 1.8 paulus */
1232 1.8 paulus inq = &sc->sc_inq;
1233 1.8 paulus rv = 1;
1234 1.8 paulus break;
1235 1.8 paulus }
1236 1.8 paulus
1237 1.8 paulus /*
1238 1.8 paulus * Put the packet on the appropriate input queue.
1239 1.8 paulus */
1240 1.8 paulus s = splimp();
1241 1.8 paulus if (IF_QFULL(inq)) {
1242 1.8 paulus IF_DROP(inq);
1243 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1244 1.8 paulus printf("ppp%d: queue full\n", sc->sc_if.if_unit);
1245 1.8 paulus sc->sc_if.if_ierrors++;
1246 1.8 paulus sc->sc_if.if_iqdrops++;
1247 1.8 paulus m_freem(m);
1248 1.8 paulus rv = 0;
1249 1.8 paulus } else
1250 1.8 paulus IF_ENQUEUE(inq, m);
1251 1.8 paulus
1252 1.8 paulus splx(s);
1253 1.8 paulus return rv;
1254 1.8 paulus }
1255 1.8 paulus
1256 1.8 paulus /*
1257 1.8 paulus * tty interface receiver interrupt.
1258 1.8 paulus */
1259 1.8 paulus static unsigned paritytab[8] = {
1260 1.8 paulus 0x96696996, 0x69969669, 0x69969669, 0x96696996,
1261 1.8 paulus 0x69969669, 0x96696996, 0x96696996, 0x69969669
1262 1.8 paulus };
1263 1.8 paulus
1264 1.1 deraadt void
1265 1.1 deraadt pppinput(c, tp)
1266 1.1 deraadt int c;
1267 1.1 deraadt register struct tty *tp;
1268 1.1 deraadt {
1269 1.1 deraadt register struct ppp_softc *sc;
1270 1.1 deraadt struct mbuf *m;
1271 1.8 paulus int ilen;
1272 1.1 deraadt
1273 1.1 deraadt tk_nin++;
1274 1.8 paulus sc = (struct ppp_softc *) tp->t_sc;
1275 1.8 paulus if (sc == NULL || tp != (struct tty *) sc->sc_devp)
1276 1.1 deraadt return;
1277 1.1 deraadt
1278 1.8 paulus ++sc->sc_bytesrcvd;
1279 1.1 deraadt
1280 1.2 paulus if (c & TTY_FE) {
1281 1.1 deraadt /* framing error or overrun on this char - abort packet */
1282 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1283 1.2 paulus printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
1284 1.1 deraadt goto flush;
1285 1.2 paulus }
1286 1.1 deraadt
1287 1.1 deraadt c &= 0xff;
1288 1.2 paulus
1289 1.8 paulus if (c & 0x80)
1290 1.8 paulus sc->sc_flags |= SC_RCV_B7_1;
1291 1.8 paulus else
1292 1.8 paulus sc->sc_flags |= SC_RCV_B7_0;
1293 1.8 paulus if (paritytab[c >> 5] & (1 << (c & 0x1F)))
1294 1.8 paulus sc->sc_flags |= SC_RCV_ODDP;
1295 1.8 paulus else
1296 1.8 paulus sc->sc_flags |= SC_RCV_EVNP;
1297 1.8 paulus
1298 1.8 paulus if (sc->sc_flags & SC_LOG_RAWIN)
1299 1.8 paulus ppplogchar(sc, c);
1300 1.2 paulus
1301 1.1 deraadt if (c == PPP_FLAG) {
1302 1.1 deraadt ilen = sc->sc_ilen;
1303 1.1 deraadt sc->sc_ilen = 0;
1304 1.8 paulus sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
1305 1.1 deraadt
1306 1.8 paulus if (sc->sc_rawin_count > 0)
1307 1.8 paulus ppplogchar(sc, -1);
1308 1.8 paulus
1309 1.8 paulus /*
1310 1.8 paulus * If SC_ESCAPED is set, then we've seen the packet
1311 1.8 paulus * abort sequence "}~".
1312 1.8 paulus */
1313 1.8 paulus if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
1314 1.1 deraadt || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
1315 1.1 deraadt #ifdef VJC
1316 1.1 deraadt /*
1317 1.1 deraadt * If we've missed a packet, we must toss subsequent compressed
1318 1.1 deraadt * packets which don't have an explicit connection ID.
1319 1.1 deraadt */
1320 1.1 deraadt sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
1321 1.1 deraadt #endif
1322 1.8 paulus if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
1323 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1324 1.12 paulus printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
1325 1.12 paulus sc->sc_fcs);
1326 1.1 deraadt sc->sc_if.if_ierrors++;
1327 1.1 deraadt } else
1328 1.8 paulus sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
1329 1.1 deraadt return;
1330 1.1 deraadt }
1331 1.1 deraadt
1332 1.8 paulus if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
1333 1.1 deraadt if (ilen) {
1334 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1335 1.2 paulus printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
1336 1.1 deraadt sc->sc_if.if_ierrors++;
1337 1.1 deraadt }
1338 1.1 deraadt return;
1339 1.1 deraadt }
1340 1.1 deraadt
1341 1.1 deraadt /*
1342 1.1 deraadt * Remove FCS trailer. Somewhat painful...
1343 1.1 deraadt */
1344 1.1 deraadt ilen -= 2;
1345 1.1 deraadt if (--sc->sc_mc->m_len == 0) {
1346 1.1 deraadt for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
1347 1.1 deraadt ;
1348 1.1 deraadt sc->sc_mc = m;
1349 1.1 deraadt }
1350 1.1 deraadt sc->sc_mc->m_len--;
1351 1.1 deraadt
1352 1.1 deraadt m = sc->sc_m;
1353 1.1 deraadt
1354 1.8 paulus if (sc->sc_flags & SC_LOG_INPKT) {
1355 1.2 paulus printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen);
1356 1.1 deraadt pppdumpm(m, ilen);
1357 1.1 deraadt }
1358 1.1 deraadt
1359 1.8 paulus if (ppppktin(sc, m, ilen)) {
1360 1.8 paulus /* Put a placeholder byte in canq for ttselect()/ttnread(). */
1361 1.1 deraadt putc(0, &tp->t_canq);
1362 1.1 deraadt ttwakeup(tp);
1363 1.1 deraadt }
1364 1.8 paulus return;
1365 1.8 paulus }
1366 1.1 deraadt
1367 1.8 paulus if (sc->sc_flags & SC_FLUSH) {
1368 1.8 paulus if (sc->sc_flags & SC_LOG_FLUSH)
1369 1.8 paulus ppplogchar(sc, c);
1370 1.1 deraadt return;
1371 1.1 deraadt }
1372 1.2 paulus
1373 1.2 paulus if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
1374 1.2 paulus return;
1375 1.1 deraadt
1376 1.1 deraadt if (sc->sc_flags & SC_ESCAPED) {
1377 1.1 deraadt sc->sc_flags &= ~SC_ESCAPED;
1378 1.1 deraadt c ^= PPP_TRANS;
1379 1.11 paulus } else if (c == PPP_ESCAPE) {
1380 1.11 paulus sc->sc_flags |= SC_ESCAPED;
1381 1.11 paulus return;
1382 1.1 deraadt }
1383 1.1 deraadt
1384 1.1 deraadt /*
1385 1.1 deraadt * Initialize buffer on first octet received.
1386 1.1 deraadt * First octet could be address or protocol (when compressing
1387 1.1 deraadt * address/control).
1388 1.1 deraadt * Second octet is control.
1389 1.1 deraadt * Third octet is first or second (when compressing protocol)
1390 1.1 deraadt * octet of protocol.
1391 1.1 deraadt * Fourth octet is second octet of protocol.
1392 1.1 deraadt */
1393 1.1 deraadt if (sc->sc_ilen == 0) {
1394 1.1 deraadt /* reset the first input mbuf */
1395 1.1 deraadt m = sc->sc_m;
1396 1.1 deraadt m->m_len = 0;
1397 1.1 deraadt m->m_data = M_DATASTART(sc->sc_m) + HDROFF;
1398 1.1 deraadt sc->sc_mc = m;
1399 1.1 deraadt sc->sc_mp = mtod(m, char *);
1400 1.1 deraadt sc->sc_fcs = PPP_INITFCS;
1401 1.1 deraadt if (c != PPP_ALLSTATIONS) {
1402 1.2 paulus if (sc->sc_flags & SC_REJ_COMP_AC) {
1403 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1404 1.8 paulus printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1405 1.8 paulus sc->sc_if.if_unit, c);
1406 1.1 deraadt goto flush;
1407 1.1 deraadt }
1408 1.1 deraadt *sc->sc_mp++ = PPP_ALLSTATIONS;
1409 1.1 deraadt *sc->sc_mp++ = PPP_UI;
1410 1.1 deraadt sc->sc_ilen += 2;
1411 1.1 deraadt m->m_len += 2;
1412 1.1 deraadt }
1413 1.1 deraadt }
1414 1.1 deraadt if (sc->sc_ilen == 1 && c != PPP_UI) {
1415 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1416 1.8 paulus printf("ppp%d: missing UI (0x3), got 0x%x\n",
1417 1.8 paulus sc->sc_if.if_unit, c);
1418 1.1 deraadt goto flush;
1419 1.1 deraadt }
1420 1.1 deraadt if (sc->sc_ilen == 2 && (c & 1) == 1) {
1421 1.8 paulus /* a compressed protocol */
1422 1.1 deraadt *sc->sc_mp++ = 0;
1423 1.1 deraadt sc->sc_ilen++;
1424 1.1 deraadt sc->sc_mc->m_len++;
1425 1.1 deraadt }
1426 1.1 deraadt if (sc->sc_ilen == 3 && (c & 1) == 0) {
1427 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1428 1.2 paulus printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1429 1.2 paulus (sc->sc_mp[-1] << 8) + c);
1430 1.1 deraadt goto flush;
1431 1.1 deraadt }
1432 1.1 deraadt
1433 1.2 paulus /* packet beyond configured mru? */
1434 1.8 paulus if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1435 1.8 paulus if (sc->sc_flags & SC_DEBUG)
1436 1.2 paulus printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1437 1.1 deraadt goto flush;
1438 1.1 deraadt }
1439 1.1 deraadt
1440 1.1 deraadt /* is this mbuf full? */
1441 1.1 deraadt m = sc->sc_mc;
1442 1.1 deraadt if (M_TRAILINGSPACE(m) <= 0) {
1443 1.1 deraadt sc->sc_mc = m = m->m_next;
1444 1.1 deraadt if (m == NULL) {
1445 1.2 paulus printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1446 1.1 deraadt goto flush;
1447 1.1 deraadt }
1448 1.1 deraadt m->m_len = 0;
1449 1.1 deraadt m->m_data = M_DATASTART(m);
1450 1.1 deraadt sc->sc_mp = mtod(m, char *);
1451 1.1 deraadt }
1452 1.1 deraadt
1453 1.1 deraadt ++m->m_len;
1454 1.1 deraadt *sc->sc_mp++ = c;
1455 1.1 deraadt sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1456 1.1 deraadt return;
1457 1.1 deraadt
1458 1.1 deraadt flush:
1459 1.8 paulus if (!(sc->sc_flags & SC_FLUSH)) {
1460 1.8 paulus sc->sc_if.if_ierrors++;
1461 1.8 paulus sc->sc_flags |= SC_FLUSH;
1462 1.8 paulus if (sc->sc_flags & SC_LOG_FLUSH)
1463 1.8 paulus ppplogchar(sc, c);
1464 1.8 paulus }
1465 1.1 deraadt }
1466 1.1 deraadt
1467 1.1 deraadt /*
1468 1.1 deraadt * Process an ioctl request to interface.
1469 1.1 deraadt */
1470 1.1 deraadt pppioctl(ifp, cmd, data)
1471 1.1 deraadt register struct ifnet *ifp;
1472 1.1 deraadt int cmd;
1473 1.1 deraadt caddr_t data;
1474 1.1 deraadt {
1475 1.1 deraadt struct proc *p = curproc; /* XXX */
1476 1.1 deraadt register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
1477 1.1 deraadt register struct ifaddr *ifa = (struct ifaddr *)data;
1478 1.1 deraadt register struct ifreq *ifr = (struct ifreq *)data;
1479 1.1 deraadt int s = splimp(), error = 0;
1480 1.1 deraadt
1481 1.1 deraadt
1482 1.1 deraadt switch (cmd) {
1483 1.1 deraadt case SIOCSIFFLAGS:
1484 1.1 deraadt if ((ifp->if_flags & IFF_RUNNING) == 0)
1485 1.1 deraadt ifp->if_flags &= ~IFF_UP;
1486 1.1 deraadt break;
1487 1.1 deraadt
1488 1.1 deraadt case SIOCSIFADDR:
1489 1.1 deraadt if (ifa->ifa_addr->sa_family != AF_INET)
1490 1.1 deraadt error = EAFNOSUPPORT;
1491 1.1 deraadt break;
1492 1.1 deraadt
1493 1.1 deraadt case SIOCSIFDSTADDR:
1494 1.1 deraadt if (ifa->ifa_addr->sa_family != AF_INET)
1495 1.1 deraadt error = EAFNOSUPPORT;
1496 1.1 deraadt break;
1497 1.1 deraadt
1498 1.1 deraadt case SIOCSIFMTU:
1499 1.1 deraadt if (error = suser(p->p_ucred, &p->p_acflag))
1500 1.12 paulus break;
1501 1.1 deraadt sc->sc_if.if_mtu = ifr->ifr_mtu;
1502 1.1 deraadt break;
1503 1.1 deraadt
1504 1.1 deraadt case SIOCGIFMTU:
1505 1.1 deraadt ifr->ifr_mtu = sc->sc_if.if_mtu;
1506 1.1 deraadt break;
1507 1.1 deraadt
1508 1.1 deraadt default:
1509 1.1 deraadt error = EINVAL;
1510 1.1 deraadt }
1511 1.1 deraadt splx(s);
1512 1.1 deraadt return (error);
1513 1.1 deraadt }
1514 1.1 deraadt
1515 1.1 deraadt #define MAX_DUMP_BYTES 128
1516 1.1 deraadt
1517 1.1 deraadt static void
1518 1.1 deraadt pppdumpm(m0, pktlen)
1519 1.1 deraadt struct mbuf *m0;
1520 1.1 deraadt int pktlen;
1521 1.1 deraadt {
1522 1.8 paulus char buf[3*MAX_DUMP_BYTES+4];
1523 1.1 deraadt char *bp = buf;
1524 1.1 deraadt struct mbuf *m;
1525 1.1 deraadt static char digits[] = "0123456789abcdef";
1526 1.1 deraadt
1527 1.1 deraadt for (m = m0; m && pktlen; m = m->m_next) {
1528 1.1 deraadt int l = m->m_len;
1529 1.1 deraadt u_char *rptr = (u_char *)m->m_data;
1530 1.1 deraadt
1531 1.1 deraadt if (pktlen > 0) {
1532 1.1 deraadt l = min(l, pktlen);
1533 1.1 deraadt pktlen -= l;
1534 1.1 deraadt }
1535 1.1 deraadt while (l--) {
1536 1.1 deraadt if (bp > buf + sizeof(buf) - 4)
1537 1.1 deraadt goto done;
1538 1.1 deraadt *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
1539 1.1 deraadt *bp++ = digits[*rptr++ & 0xf];
1540 1.1 deraadt }
1541 1.1 deraadt
1542 1.1 deraadt if (m->m_next) {
1543 1.1 deraadt if (bp > buf + sizeof(buf) - 3)
1544 1.1 deraadt goto done;
1545 1.1 deraadt *bp++ = '|';
1546 1.8 paulus } else
1547 1.8 paulus *bp++ = ' ';
1548 1.1 deraadt }
1549 1.1 deraadt done:
1550 1.1 deraadt if (m && pktlen)
1551 1.1 deraadt *bp++ = '>';
1552 1.1 deraadt *bp = 0;
1553 1.1 deraadt printf("%s\n", buf);
1554 1.1 deraadt }
1555 1.1 deraadt
1556 1.1 deraadt static void
1557 1.8 paulus ppplogchar(sc, c)
1558 1.8 paulus struct ppp_softc *sc;
1559 1.8 paulus int c;
1560 1.8 paulus {
1561 1.8 paulus if (c >= 0)
1562 1.8 paulus sc->sc_rawin[sc->sc_rawin_count++] = c;
1563 1.8 paulus if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1564 1.8 paulus || c < 0 && sc->sc_rawin_count > 0) {
1565 1.8 paulus printf("ppp%d input: ", sc->sc_if.if_unit);
1566 1.8 paulus pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1567 1.8 paulus sc->sc_rawin_count = 0;
1568 1.8 paulus }
1569 1.8 paulus }
1570 1.8 paulus
1571 1.8 paulus static void
1572 1.1 deraadt pppdumpb(b, l)
1573 1.1 deraadt u_char *b;
1574 1.1 deraadt int l;
1575 1.1 deraadt {
1576 1.8 paulus char buf[3*MAX_DUMP_BYTES+4];
1577 1.1 deraadt char *bp = buf;
1578 1.1 deraadt static char digits[] = "0123456789abcdef";
1579 1.1 deraadt
1580 1.1 deraadt while (l--) {
1581 1.8 paulus if (bp >= buf + sizeof(buf) - 3) {
1582 1.1 deraadt *bp++ = '>';
1583 1.1 deraadt break;
1584 1.1 deraadt }
1585 1.8 paulus *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1586 1.8 paulus *bp++ = digits[*b++ & 0xf];
1587 1.8 paulus *bp++ = ' ';
1588 1.1 deraadt }
1589 1.1 deraadt
1590 1.1 deraadt *bp = 0;
1591 1.1 deraadt printf("%s\n", buf);
1592 1.1 deraadt }
1593 1.1 deraadt
1594 1.1 deraadt
1595 1.1 deraadt #endif /* NPPP > 0 */
1596