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