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