133183Sbostic /* 233183Sbostic * Copyright (c) 1987 Regents of the University of California. 333183Sbostic * All rights reserved. 433183Sbostic * 533183Sbostic * Redistribution and use in source and binary forms are permitted 634844Sbostic * provided that the above copyright notice and this paragraph are 734844Sbostic * duplicated in all such forms and that any documentation, 834844Sbostic * advertising materials, and other materials related to such 934844Sbostic * distribution and use acknowledge that the software was developed 1034844Sbostic * by the University of California, Berkeley. The name of the 1134844Sbostic * University may not be used to endorse or promote products derived 1234844Sbostic * from this software without specific prior written permission. 1334844Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434844Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534844Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633183Sbostic * 17*38365Swilliam * @(#)if_sl.c 7.15 (Berkeley) 06/29/89 1833183Sbostic */ 1926122Skarels 2026121Skarels /* 2126121Skarels * Serial Line interface 2226121Skarels * 2326121Skarels * Rick Adams 2426121Skarels * Center for Seismic Studies 2526121Skarels * 1300 N 17th Street, Suite 1450 2626121Skarels * Arlington, Virginia 22209 2726121Skarels * (703)276-7900 2826121Skarels * rick@seismo.ARPA 2926121Skarels * seismo!rick 3026121Skarels * 3126121Skarels * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris). 3226378Skarels * N.B.: this belongs in netinet, not net, the way it stands now. 3326122Skarels * Should have a link-layer type designation, but wouldn't be 3426122Skarels * backwards-compatible. 3526121Skarels * 3626121Skarels * Converted to 4.3BSD Beta by Chris Torek. 3726378Skarels * Other changes made at Berkeley, based in part on code by Kirk Smith. 38*38365Swilliam * W. Jolitz, added slip abort & time domain window 39*38365Swilliam * also added Van Jacobson's hdr compression code 4026121Skarels */ 4126121Skarels 4226121Skarels /* $Header: if_sl.c,v 1.12 85/12/20 21:54:55 chris Exp $ */ 4326121Skarels /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */ 4426121Skarels 4526121Skarels #include "sl.h" 4626121Skarels #if NSL > 0 4726121Skarels 4826121Skarels #include "param.h" 49*38365Swilliam #include "dir.h" 5038280Swilliam #include "user.h" 5126121Skarels #include "mbuf.h" 5226121Skarels #include "buf.h" 5337472Ssklower #include "dkstat.h" 5426121Skarels #include "socket.h" 5526121Skarels #include "ioctl.h" 5626378Skarels #include "file.h" 5726121Skarels #include "tty.h" 58*38365Swilliam #include "kernel.h" 59*38365Swilliam #include "conf.h" 6026121Skarels #include "errno.h" 6126121Skarels 6226378Skarels #include "if.h" 6326378Skarels #include "netisr.h" 6426378Skarels #include "route.h" 6526378Skarels #if INET 6626121Skarels #include "../netinet/in.h" 6726121Skarels #include "../netinet/in_systm.h" 6828986Skarels #include "../netinet/in_var.h" 6926121Skarels #include "../netinet/ip.h" 70*38365Swilliam #include "slcompress.h" 7126378Skarels #endif 72*38365Swilliam #include "if_slvar.h" 7326121Skarels 7437500Smckusick #include "machine/mtpr.h" 7526121Skarels 7626121Skarels /* 7726378Skarels * N.B.: SLMTU is now a hard limit on input packet size. 7833980Skarels * SLMTU must be <= MCLBYTES - sizeof(struct ifnet *). 7926121Skarels */ 8026121Skarels #define SLMTU 1006 8126378Skarels #define SLIP_HIWAT 1000 /* don't start a new packet if HIWAT on queue */ 8226378Skarels #define CLISTRESERVE 1000 /* Can't let clists get too low */ 8326121Skarels 84*38365Swilliam /* 85*38365Swilliam * SLIP ABORT ESCAPE MECHANISM: 86*38365Swilliam * (inspired by HAYES modem escape arrangement) 87*38365Swilliam * 1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape } 88*38365Swilliam * signals a "soft" exit from slip mode by usermode process 89*38365Swilliam * (hard exit unimplemented -- currently system dependant) 90*38365Swilliam */ 9126121Skarels 92*38365Swilliam #define ABT_ESC '\033' /* can't be t_intr - distant host must know it*/ 93*38365Swilliam #define ABT_WAIT 1 /* in seconds - idle before an escape & after */ 94*38365Swilliam #define ABT_RECYCLE (5*2+2) /* in seconds - time window processing abort */ 9526121Skarels 96*38365Swilliam /* a "soft" abort means to pass a suggestion to user code to abort slip */ 97*38365Swilliam #define ABT_SOFT 3 /* count of escapes */ 98*38365Swilliam 99*38365Swilliam /* a "hard" abort means to force abort slip within the kernel -- process jam? */ 100*38365Swilliam #define ABT_HARD 5 /* count of escapes */ 101*38365Swilliam 102*38365Swilliam /* 103*38365Swilliam * SLIP TIME WINDOW: 104*38365Swilliam * Only accept packets with octets that come at least this often. 105*38365Swilliam * With non-reliable but fast modems (FAX, Packet Radio), we assume that 106*38365Swilliam * packets come in groups (time domain), and that fractional groups that 107*38365Swilliam * come erratically are just noise that will foul subsequent packets. 108*38365Swilliam * We reject them on a time filter basis. 109*38365Swilliam * 110*38365Swilliam * This is a very coarse filter, because error correcting modems like the 111*38365Swilliam * telebit take there own sweet time encoding/decoding packets. If you 112*38365Swilliam * are using an MNP,PEP or other such arrangement, this won't help much. 113*38365Swilliam * If you are using packet radio, use the millisecond time val with 114*38365Swilliam * as small a resolution as possible. In any case, the coarse filter 115*38365Swilliam * saves noisey lines about 50 % of the time. 116*38365Swilliam */ 117*38365Swilliam 118*38365Swilliam #define TIME_WINDOW 2 /* max seconds between valid packet chars */ 119*38365Swilliam 120*38365Swilliam struct sl_softc sl_softc[NSL]; 121*38365Swilliam 12226121Skarels #define FRAME_END 0300 /* Frame End */ 12326121Skarels #define FRAME_ESCAPE 0333 /* Frame Esc */ 12426121Skarels #define TRANS_FRAME_END 0334 /* transposed frame end */ 12526121Skarels #define TRANS_FRAME_ESCAPE 0335 /* transposed frame esc */ 12626121Skarels 12726121Skarels #define t_sc T_LINEP 12826121Skarels 12926121Skarels int sloutput(), slioctl(), ttrstrt(); 13026121Skarels 13126121Skarels /* 13226121Skarels * Called from boot code to establish sl interfaces. 13326121Skarels */ 13426121Skarels slattach() 13526121Skarels { 13626121Skarels register struct sl_softc *sc; 13726121Skarels register int i = 0; 13826121Skarels 13926121Skarels for (sc = sl_softc; i < NSL; sc++) { 14026121Skarels sc->sc_if.if_name = "sl"; 14126121Skarels sc->sc_if.if_unit = i++; 14226121Skarels sc->sc_if.if_mtu = SLMTU; 14326121Skarels sc->sc_if.if_flags = IFF_POINTOPOINT; 14426121Skarels sc->sc_if.if_ioctl = slioctl; 14526121Skarels sc->sc_if.if_output = sloutput; 14626121Skarels sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; 14726121Skarels if_attach(&sc->sc_if); 14826121Skarels } 14926121Skarels } 15026121Skarels 15126121Skarels /* 15226121Skarels * Line specific open routine. 15326121Skarels * Attach the given tty to the first available sl unit. 15426121Skarels */ 15526378Skarels /* ARGSUSED */ 15626121Skarels slopen(dev, tp) 15726121Skarels dev_t dev; 15826121Skarels register struct tty *tp; 15926121Skarels { 16026121Skarels register struct sl_softc *sc; 16126121Skarels register int nsl; 16237549Smckusick int error; 16326121Skarels 16437549Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 16537549Smckusick return (error); 16626378Skarels if (tp->t_line == SLIPDISC) 16726121Skarels return (EBUSY); 16826121Skarels 16926121Skarels for (nsl = 0, sc = sl_softc; nsl < NSL; nsl++, sc++) 17026121Skarels if (sc->sc_ttyp == NULL) { 17126121Skarels sc->sc_flags = 0; 17226121Skarels sc->sc_ilen = 0; 17326378Skarels if (slinit(sc) == 0) 17426378Skarels return (ENOBUFS); 175*38365Swilliam #ifdef INET 176*38365Swilliam sl_compress_init(&sc->sc_comp); 177*38365Swilliam #endif 17826121Skarels tp->t_sc = (caddr_t)sc; 17926121Skarels sc->sc_ttyp = tp; 18026378Skarels ttyflush(tp, FREAD | FWRITE); 18126121Skarels return (0); 18226121Skarels } 18326121Skarels 18426378Skarels return (ENXIO); 18526121Skarels } 18626121Skarels 18726121Skarels /* 18826121Skarels * Line specific close routine. 18926121Skarels * Detach the tty from the sl unit. 19026121Skarels * Mimics part of ttyclose(). 19126121Skarels */ 19226121Skarels slclose(tp) 19326121Skarels struct tty *tp; 19426121Skarels { 19526121Skarels register struct sl_softc *sc; 19626121Skarels int s; 19726121Skarels 19826121Skarels ttywflush(tp); 19926121Skarels tp->t_line = 0; 20026121Skarels s = splimp(); /* paranoid; splnet probably ok */ 20126121Skarels sc = (struct sl_softc *)tp->t_sc; 20226121Skarels if (sc != NULL) { 20326121Skarels if_down(&sc->sc_if); 20426121Skarels sc->sc_ttyp = NULL; 20526121Skarels tp->t_sc = NULL; 20626378Skarels MCLFREE((struct mbuf *)sc->sc_buf); 20726378Skarels sc->sc_buf = 0; 208*38365Swilliam sc->sc_mp = (char *) 4; /*XXX!?! */ 20926121Skarels } 21026121Skarels splx(s); 21126121Skarels } 21226121Skarels 21326121Skarels /* 21426121Skarels * Line specific (tty) ioctl routine. 21526121Skarels * Provide a way to get the sl unit number. 21626121Skarels */ 21726378Skarels /* ARGSUSED */ 21826121Skarels sltioctl(tp, cmd, data, flag) 21926121Skarels struct tty *tp; 22026121Skarels caddr_t data; 22126121Skarels { 222*38365Swilliam struct sl_softc *sc = (struct sl_softc *)tp->t_sc; 223*38365Swilliam int s; 22426121Skarels 225*38365Swilliam switch (cmd) { 226*38365Swilliam case TIOCGETD: 227*38365Swilliam *(int *)data = sc->sc_if.if_unit; 228*38365Swilliam break; 229*38365Swilliam case TIOCMGET: 23038280Swilliam if (tp->t_state&TS_CARR_ON) 23138280Swilliam *(int *)data = TIOCM_CAR ; 232*38365Swilliam else *(int *)data = 0 ; 233*38365Swilliam 234*38365Swilliam if (sc->sc_flags&SC_ABORT) 235*38365Swilliam *(int *)data |= TIOCM_DTR ; 236*38365Swilliam break; 237*38365Swilliam case SLIOCGFLAGS: 238*38365Swilliam *(int *)data = sc->sc_flags; 239*38365Swilliam break; 240*38365Swilliam case SLIOCSFLAGS: 241*38365Swilliam #define SC_MASK (SC_COMPRESS|SC_NOICMP) 242*38365Swilliam s = splimp(); 243*38365Swilliam sc->sc_flags = 244*38365Swilliam (sc->sc_flags &~ SC_MASK) | ((*(int *)data) & SC_MASK); 245*38365Swilliam splx(s); 246*38365Swilliam break; 247*38365Swilliam default: 248*38365Swilliam return (-1); 24938280Swilliam } 250*38365Swilliam return (0); 25126121Skarels } 25226121Skarels 25326121Skarels /* 25426121Skarels * Queue a packet. Start transmission if not active. 25526121Skarels */ 25626121Skarels sloutput(ifp, m, dst) 25726121Skarels register struct ifnet *ifp; 25826121Skarels register struct mbuf *m; 25926121Skarels struct sockaddr *dst; 26026121Skarels { 26126121Skarels register struct sl_softc *sc; 26226121Skarels int s; 26326121Skarels 26426121Skarels /* 26526121Skarels * `Cannot happen' (see slioctl). Someday we will extend 26626121Skarels * the line protocol to support other address families. 26726121Skarels */ 26826121Skarels if (dst->sa_family != AF_INET) { 26926121Skarels printf("sl%d: af%d not supported\n", ifp->if_unit, 27026121Skarels dst->sa_family); 27126121Skarels m_freem(m); 27226121Skarels return (EAFNOSUPPORT); 27326121Skarels } 27426121Skarels 27526121Skarels sc = &sl_softc[ifp->if_unit]; 27626121Skarels if (sc->sc_ttyp == NULL) { 27726121Skarels m_freem(m); 27826121Skarels return (ENETDOWN); /* sort of */ 27926121Skarels } 28026899Skarels if ((sc->sc_ttyp->t_state & TS_CARR_ON) == 0) { 28126899Skarels m_freem(m); 28226899Skarels return (EHOSTUNREACH); 28326899Skarels } 28426121Skarels s = splimp(); 285*38365Swilliam #ifdef INET 286*38365Swilliam if (sc->sc_flags & (SC_COMPRESS|SC_NOICMP)) { 287*38365Swilliam register struct ip *ip = mtod(m, struct ip *); 288*38365Swilliam if (ip->ip_p == IPPROTO_TCP) { 289*38365Swilliam /* add stuff to TOS routing */ 290*38365Swilliam if (sc->sc_flags & SC_COMPRESS) 291*38365Swilliam (void) sl_compress_tcp(m, ip, &sc->sc_comp); 292*38365Swilliam } else if ((sc->sc_flags & SC_NOICMP) && 293*38365Swilliam ip->ip_p == IPPROTO_ICMP) { 294*38365Swilliam m_freem(m); 295*38365Swilliam splx(s); 296*38365Swilliam return (0); 297*38365Swilliam } 298*38365Swilliam } 299*38365Swilliam #endif 30026121Skarels if (IF_QFULL(&ifp->if_snd)) { 30126121Skarels IF_DROP(&ifp->if_snd); 30226121Skarels splx(s); 30326121Skarels m_freem(m); 30426378Skarels sc->sc_if.if_oerrors++; 30526121Skarels return (ENOBUFS); 30626121Skarels } 30726121Skarels IF_ENQUEUE(&ifp->if_snd, m); 30833740Skarels if (sc->sc_ttyp->t_outq.c_cc == 0) { 30926121Skarels splx(s); 31026121Skarels slstart(sc->sc_ttyp); 31126121Skarels } else 31226121Skarels splx(s); 31326121Skarels return (0); 31426121Skarels } 31526121Skarels 31626121Skarels /* 31726121Skarels * Start output on interface. Get another datagram 31826121Skarels * to send from the interface queue and map it to 31926121Skarels * the interface before starting output. 32026121Skarels */ 32126121Skarels slstart(tp) 32226121Skarels register struct tty *tp; 32326121Skarels { 32426121Skarels register struct sl_softc *sc = (struct sl_softc *)tp->t_sc; 32526121Skarels register struct mbuf *m; 32626378Skarels register int len; 32726378Skarels register u_char *cp; 32833740Skarels int nd, np, n, s; 32926378Skarels struct mbuf *m2; 33026378Skarels extern int cfreecount; 33126121Skarels 33226378Skarels for (;;) { 33326378Skarels /* 33426378Skarels * If there is more in the output queue, just send it now. 33526378Skarels * We are being called in lieu of ttstart and must do what 33626378Skarels * it would. 33726378Skarels */ 33826378Skarels if (tp->t_outq.c_cc > 0) 33926378Skarels ttstart(tp); 34026378Skarels if (tp->t_outq.c_cc > SLIP_HIWAT) 34126378Skarels return; 34226121Skarels 34326378Skarels /* 34426378Skarels * This happens briefly when the line shuts down. 34526378Skarels */ 34626378Skarels if (sc == NULL) 34726378Skarels return; 34826121Skarels 34926378Skarels /* 35026378Skarels * If system is getting low on clists 35126378Skarels * and we have something running already, stop here. 35226378Skarels */ 35334361Skarels if (cfreecount < CLISTRESERVE + SLMTU && tp->t_outq.c_cc) 35426378Skarels return; 35526121Skarels 35626378Skarels /* 35726378Skarels * Get a packet and send it to the interface. 35826378Skarels */ 35926378Skarels s = splimp(); 36026378Skarels IF_DEQUEUE(&sc->sc_if.if_snd, m); 36133740Skarels splx(s); 36233740Skarels if (m == NULL) 36326378Skarels return; 36426121Skarels 36526378Skarels /* 36626378Skarels * The extra FRAME_END will start up a new packet, and thus 36726378Skarels * will flush any accumulated garbage. We do this whenever 36826378Skarels * the line may have been idle for some time. 36926378Skarels */ 37033740Skarels if (tp->t_outq.c_cc == 0) 37126378Skarels (void) putc(FRAME_END, &tp->t_outq); 37226378Skarels 37326378Skarels while (m) { 37426378Skarels cp = mtod(m, u_char *); 37526378Skarels len = m->m_len; 37626378Skarels while (len > 0) { 37726378Skarels /* 37826378Skarels * Find out how many bytes in the string we can 37926378Skarels * handle without doing something special. 38026378Skarels */ 38126378Skarels nd = locc(FRAME_ESCAPE, len, cp); 38226378Skarels np = locc(FRAME_END, len, cp); 38326378Skarels n = len - MAX(nd, np); 38426378Skarels if (n) { 38526378Skarels /* 38626378Skarels * Put n characters at once 38726378Skarels * into the tty output queue. 38826378Skarels */ 38926378Skarels if (b_to_q((char *)cp, n, &tp->t_outq)) 39026378Skarels break; 39127688Smckusick len -= n; 39227688Smckusick cp += n; 39326121Skarels } 39426378Skarels /* 39526378Skarels * If there are characters left in the mbuf, 39626378Skarels * the first one must be special.. 39726378Skarels * Put it out in a different form. 39826378Skarels */ 39926378Skarels if (len) { 40026378Skarels if (putc(FRAME_ESCAPE, &tp->t_outq)) 40126378Skarels break; 40226378Skarels if (putc(*cp == FRAME_ESCAPE ? 40326378Skarels TRANS_FRAME_ESCAPE : TRANS_FRAME_END, 40426378Skarels &tp->t_outq)) { 40526378Skarels (void) unputc(&tp->t_outq); 40626378Skarels break; 40726378Skarels } 40826378Skarels cp++; 40926378Skarels len--; 41026378Skarels } 41126378Skarels } 41226378Skarels MFREE(m, m2); 41326378Skarels m = m2; 41426121Skarels } 41526378Skarels 41626378Skarels if (putc(FRAME_END, &tp->t_outq)) { 41726378Skarels /* 41826378Skarels * Not enough room. Remove a char to make room 41926378Skarels * and end the packet normally. 42026378Skarels * If you get many collisions (more than one or two 42126378Skarels * a day) you probably do not have enough clists 42226378Skarels * and you should increase "nclist" in param.c. 42326378Skarels */ 42426378Skarels (void) unputc(&tp->t_outq); 42526378Skarels (void) putc(FRAME_END, &tp->t_outq); 42626378Skarels sc->sc_if.if_collisions++; 42726378Skarels } else 42826378Skarels sc->sc_if.if_opackets++; 42926121Skarels } 43026378Skarels } 43126121Skarels 43226378Skarels slinit(sc) 43326378Skarels register struct sl_softc *sc; 43426378Skarels { 43537472Ssklower register caddr_t p; 43626121Skarels 43726378Skarels if (sc->sc_buf == (char *) 0) { 43837472Ssklower MCLALLOC(p, M_WAIT); 43926378Skarels if (p) { 44037472Ssklower sc->sc_buf = p; 44137472Ssklower sc->sc_mp = p; 44226378Skarels } else { 44326378Skarels printf("sl%d: can't allocate buffer\n", sc - sl_softc); 44426378Skarels sc->sc_if.if_flags &= ~IFF_UP; 44526378Skarels return (0); 44626378Skarels } 44726378Skarels } 44826378Skarels return (1); 44926121Skarels } 45026121Skarels 45126121Skarels /* 45226121Skarels * Copy data buffer to mbuf chain; add ifnet pointer ifp. 45326121Skarels */ 45426121Skarels struct mbuf * 45526378Skarels sl_btom(sc, len, ifp) 45626378Skarels struct sl_softc *sc; 45726121Skarels register int len; 45826121Skarels struct ifnet *ifp; 45926121Skarels { 46026378Skarels register caddr_t cp; 46126121Skarels register struct mbuf *m, **mp; 46226378Skarels register unsigned count; 46326121Skarels struct mbuf *top = NULL; 46426121Skarels 46538280Swilliam cp = sc->sc_buf; 46626121Skarels mp = ⊤ 46738280Swilliam 46826121Skarels while (len > 0) { 46937472Ssklower if (top == NULL) { 47037472Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 47137472Ssklower } else { 47237472Ssklower MGET(m, M_DONTWAIT, MT_DATA); 47337472Ssklower } 47438280Swilliam if (m == NULL) { 47526121Skarels m_freem(top); 47626121Skarels return (NULL); 47726121Skarels } 47837472Ssklower if (top == NULL) { 47937472Ssklower m->m_pkthdr.rcvif = ifp; 48037472Ssklower m->m_pkthdr.len = len; 48137472Ssklower m->m_len = MHLEN; 48237472Ssklower } else 48337472Ssklower m->m_len = MLEN; 48438280Swilliam *mp = m; 48526378Skarels /* 48637472Ssklower * If we have at least MINCLSIZE bytes, 48737472Ssklower * allocate a new page. Swap the current 48837472Ssklower * buffer page with the new one. 48926378Skarels */ 49037472Ssklower if (len >= MINCLSIZE) { 49137472Ssklower MCLGET(m, M_DONTWAIT); 49237472Ssklower if (m->m_flags & M_EXT) { 49326378Skarels cp = mtod(m, char *); 49437472Ssklower m->m_data = sc->sc_buf; 49528184Smckusick sc->sc_buf = cp; 49637472Ssklower count = MIN(len, MCLBYTES); 49726378Skarels goto nocopy; 49826378Skarels } 49926121Skarels } 50037472Ssklower count = MIN(len, m->m_len); 50126378Skarels bcopy(cp, mtod(m, caddr_t), count); 50226378Skarels nocopy: 50326121Skarels m->m_len = count; 50426378Skarels cp += count; 50526121Skarels len -= count; 50626121Skarels mp = &m->m_next; 50726121Skarels } 50826121Skarels return (top); 50926121Skarels } 51026121Skarels 51126121Skarels /* 51226121Skarels * tty interface receiver interrupt. 51326121Skarels */ 51426121Skarels slinput(c, tp) 51526121Skarels register int c; 51626121Skarels register struct tty *tp; 51726121Skarels { 51826121Skarels register struct sl_softc *sc; 51926121Skarels register struct mbuf *m; 52026121Skarels int s; 52126121Skarels 52226378Skarels tk_nin++; 52326121Skarels sc = (struct sl_softc *)tp->t_sc; 52426121Skarels if (sc == NULL) 52526121Skarels return; 526*38365Swilliam if (!(tp->t_state&TS_CARR_ON)) /*XXX*/ 527*38365Swilliam return; 52826121Skarels 52926121Skarels c &= 0xff; 530*38365Swilliam 531*38365Swilliam /* if we see an abort after "idle" time, count it */ 532*38365Swilliam if ((c&0x7f) == ABT_ESC && time.tv_sec >= sc->sc_lasttime + ABT_WAIT) { 533*38365Swilliam sc->sc_abortcount++; 534*38365Swilliam /* record when the first abort escape arrived */ 535*38365Swilliam if (sc->sc_abortcount == 1) sc->sc_starttime = time.tv_sec; 536*38365Swilliam } 537*38365Swilliam 538*38365Swilliam /* if we have an abort, see that we have not run out of time, or 539*38365Swilliam that we have an "idle" time after the complete escape sequence */ 540*38365Swilliam if (sc->sc_abortcount) { 541*38365Swilliam if (time.tv_sec >= sc->sc_starttime + ABT_RECYCLE) 542*38365Swilliam sc->sc_abortcount = 0; 543*38365Swilliam if (sc->sc_abortcount >= ABT_SOFT 544*38365Swilliam && time.tv_sec >= sc->sc_lasttime + ABT_WAIT) 545*38365Swilliam sc->sc_flags |= SC_ABORT; 546*38365Swilliam } 547*38365Swilliam 548*38365Swilliam if (sc->sc_ilen && time.tv_sec >= sc->sc_lasttime + TIME_WINDOW) { 549*38365Swilliam sc->sc_flags &= ~SC_ESCAPED; 550*38365Swilliam sc->sc_mp = sc->sc_buf; 551*38365Swilliam sc->sc_ilen = 0; 552*38365Swilliam sc->sc_if.if_ierrors++; 553*38365Swilliam return; 554*38365Swilliam } 555*38365Swilliam 556*38365Swilliam sc->sc_lasttime = time.tv_sec; 557*38365Swilliam 55826121Skarels if (sc->sc_flags & SC_ESCAPED) { 55926121Skarels sc->sc_flags &= ~SC_ESCAPED; 56026121Skarels switch (c) { 56126121Skarels 56226121Skarels case TRANS_FRAME_ESCAPE: 56326121Skarels c = FRAME_ESCAPE; 56426121Skarels break; 56526121Skarels 56626121Skarels case TRANS_FRAME_END: 56726121Skarels c = FRAME_END; 56826121Skarels break; 56926121Skarels 57026121Skarels default: 57126121Skarels sc->sc_if.if_ierrors++; 57238280Swilliam sc->sc_mp = sc->sc_buf; 57326121Skarels sc->sc_ilen = 0; 57426121Skarels return; 57526121Skarels } 57626121Skarels } else { 57726121Skarels switch (c) { 57826121Skarels 57926121Skarels case FRAME_END: 58026121Skarels if (sc->sc_ilen == 0) /* ignore */ 58126121Skarels return; 58226378Skarels m = sl_btom(sc, sc->sc_ilen, &sc->sc_if); 583*38365Swilliam sc->sc_mp = sc->sc_buf; 584*38365Swilliam sc->sc_ilen = 0; 58526121Skarels if (m == NULL) { 58626121Skarels sc->sc_if.if_ierrors++; 58726121Skarels return; 58826121Skarels } 58926121Skarels sc->sc_if.if_ipackets++; 590*38365Swilliam #ifdef INET 591*38365Swilliam { u_char type = *mtod(m, u_char *); 592*38365Swilliam if (!(m = sl_uncompress_tcp(m, type&0xf0, &sc->sc_comp))) 593*38365Swilliam return; 594*38365Swilliam } 595*38365Swilliam #endif 59626121Skarels s = splimp(); 59726121Skarels if (IF_QFULL(&ipintrq)) { 59826121Skarels IF_DROP(&ipintrq); 59926121Skarels sc->sc_if.if_ierrors++; 60026121Skarels m_freem(m); 60126121Skarels } else { 60226121Skarels IF_ENQUEUE(&ipintrq, m); 60326121Skarels schednetisr(NETISR_IP); 60426121Skarels } 60526121Skarels splx(s); 60626121Skarels return; 60726121Skarels 60826121Skarels case FRAME_ESCAPE: 60926121Skarels sc->sc_flags |= SC_ESCAPED; 61026121Skarels return; 61126121Skarels } 61226121Skarels } 61328200Skarels if (++sc->sc_ilen > SLMTU) { 61426121Skarels sc->sc_if.if_ierrors++; 61538280Swilliam sc->sc_mp = sc->sc_buf; 61626121Skarels sc->sc_ilen = 0; 61726121Skarels return; 61826121Skarels } 61926121Skarels *sc->sc_mp++ = c; 62026121Skarels } 62126121Skarels 62226121Skarels /* 62326121Skarels * Process an ioctl request. 62426121Skarels */ 62526121Skarels slioctl(ifp, cmd, data) 62626121Skarels register struct ifnet *ifp; 62726121Skarels int cmd; 62826121Skarels caddr_t data; 62926121Skarels { 63026121Skarels register struct ifaddr *ifa = (struct ifaddr *)data; 63126121Skarels int s = splimp(), error = 0; 63226121Skarels 63326121Skarels switch (cmd) { 63426121Skarels 63526121Skarels case SIOCSIFADDR: 63637472Ssklower if (ifa->ifa_addr->sa_family == AF_INET) 63726121Skarels ifp->if_flags |= IFF_UP; 63826121Skarels else 63926121Skarels error = EAFNOSUPPORT; 64026121Skarels break; 64126121Skarels 64226121Skarels case SIOCSIFDSTADDR: 64337472Ssklower if (ifa->ifa_addr->sa_family != AF_INET) 64426121Skarels error = EAFNOSUPPORT; 64526121Skarels break; 64626121Skarels 64726121Skarels default: 64826121Skarels error = EINVAL; 64926121Skarels } 65026121Skarels splx(s); 65126121Skarels return (error); 65226121Skarels } 65326121Skarels #endif 654