📄 if_sl.c
字号:
*/ if (ifDstAddrSet (slipName, peerAddr) == ERROR || ifAddrSet (slipName, myAddr) == ERROR || routeAdd (myAddr, myAddr) == ERROR) { (void) close (slipFd); return (ERROR); } /* start up the SLIP output task for this interface */ sc->sc_wrtTaskId = taskSpawn (slipWrtName, slipTaskPriority, slipTaskOptions, slipTaskStackSize, (FUNCPTR) slipWrtTask, (int) sc, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (sc->sc_wrtTaskId == ERROR) { (void) close (slipFd); return (ERROR); } return (OK); }/********************************************************************************* slipBaudSet - set the baud rate for a SLIP interface** This routine adjusts the baud rate of a tty device attached to a SLIP* interface. It provides a way to modify the baud rate of a tty* device being used as a SLIP interface.** RETURNS: OK, or ERROR if the unit number is invalid or uninitialized.*/STATUS slipBaudSet ( int unit, /* SLIP device unit number */ int baud /* baud rate */ ) { SL_SOFTC *sc; /* check for valid unit number */ if (unit < 0 || unit >= NSLIP) { (void)errnoSet (S_if_sl_INVALID_UNIT_NUMBER); return (ERROR); } /* make sure that the sl_softc for the 'unit' is initialized properly */ if ((sc = sl_softc [unit]) == NULL) { (void)errnoSet (S_if_sl_UNIT_UNINITIALIZED); return (ERROR); } return (ioctl (sc->sc_fd, FIOBAUDRATE, baud)); }/********************************************************************************* slattach - publish the `sl' network interface and initialize the driver and device** This routine publishes the `sl' interface by filling in a network interface* record and adding this record to the system list. It also initializes* the driver and the device to the operational state.** This routine is usually called by slipInit().** RETURNS: OK or ERROR.*/STATUS slattach ( int unit, /* SLIP device unit number */ int fd, /* fd of tty device for SLIP interface */ BOOL compressEnable, /* explicitly enable CSLIP compression */ BOOL compressAllow, /* enable CSLIP compression on Rx */ int mtu /* user setable MTU */ ) { SL_SOFTC *sc; struct ifnet *ifp; int ix; if (sl_softc [unit] != NULL) { (void)errnoSet (S_if_sl_UNIT_ALREADY_INITIALIZED); return (ERROR); } if ((sc = (SL_SOFTC *) calloc (1, sizeof (SL_SOFTC))) == (SL_SOFTC *) NULL) return (ERROR); if (mtu <= 0 || mtu > 2048) mtu = SLMTU; sl_softc [unit] = sc; ifp = &sc->sc_if; /* get a pointer to ifnet structure */ ifp->if_name = "sl"; ifp->if_unit = unit; ifp->if_mtu = mtu; ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; sc->sc_if.if_type = IFT_SLIP; ifp->if_ioctl = slioctl; ifp->if_init = (FUNCPTR) slinit; ifp->if_output = sloutput; ifp->if_reset = slipDelete; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; if_attach (ifp); /* attach SLIP to linked list of all interfaces */ sc->sc_flags = 0; sc->sc_ilen = 0; sc->sc_qlen = 0; sc->sc_nLoanRxBuf = L_POOL; /* set CSLIP options in the SL_SOFTC flags */ if (compressEnable || compressAllow) { sl_compress_init (&sc->sc_comp); if (compressEnable) sc->sc_flags |= SL_COMPRESS; else sc->sc_flags |= SL_COMPRESS_RX; } /* allocate SLIP input buffer space, including loaner buffers */ if ((sc->sc_orig = (char *) calloc (L_POOL, (u_int) SLBUFSIZE)) == NULL) { slSoftcFree (sc, unit); return (ERROR); } sc->sc_buf = sc->sc_orig + SLBUF_OFF; /* leave space for uncompress */ /* assign loaner buffer addresses */ for (ix = 0; ix < L_POOL; ix++) { sc->sc_lPool[ix] = (sc->sc_buf + (ix * SLBUFSIZE)); sc->sc_refC[ix] = 0; sc->sc_pRefC[ix] = &sc->sc_refC[ix]; } if ((sc->sc_wrtSem = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY)) == NULL) { slSoftcFree (sc, unit); return (ERROR); } /* * Make sure that the tty device described by 'fd' is * indeed a tty device. */ if (ioctl (fd, FIOISATTY, 0 /*XXX*/) == TRUE) sc->sc_fd = fd; else { slSoftcFree (sc, unit); return (ERROR); } /* * call ioctl to, * FIOFLUSH - flush out everything on this tty dev * FIOOPTIONS - set the tty dev in RAW mode * FIOPROTOHOOK - specify the protocol interface hook routine for SLIP * FIOPROTOARG - specify the SLIP unit number for this tty dev */ if (ioctl (fd, FIOFLUSH, 0 /*XXX*/) == ERROR || ioctl (fd, FIOOPTIONS, OPT_RAW) == ERROR || ioctl (fd, FIOPROTOHOOK, (int) slintr) == ERROR || ioctl (fd, FIOPROTOARG, unit) == ERROR) { slSoftcFree (sc, unit); return (ERROR); } return (OK); }/********************************************************************************* slipDelete - delete a SLIP interface** This routine resets a specified SLIP interface. It detaches the tty from* the `sl' unit and deletes the specified SLIP interface from the list of* network interfaces. For example, the following call will delete the first* SLIP interface from the list of network interfaces:* .CS* slipDelete (0);* .CE** RETURNS: OK, or ERROR if the unit number is invalid or uninitialized.*/STATUS slipDelete ( int unit /* SLIP unit number */ ) { SL_SOFTC *sc; struct mbuf *pMbuf; int s; if (unit >= 0 && unit < NSLIP) sc = sl_softc [unit]; else { (void)errnoSet (S_if_sl_INVALID_UNIT_NUMBER); return (ERROR); } if (sc == NULL) { (void)errnoSet (S_if_sl_UNIT_UNINITIALIZED); return (ERROR); } /* flush write side of the tty ringer buffer */ (void) ioctl (sc->sc_fd, FIOWFLUSH, 0 /*XXX*/); (void) ioctl (sc->sc_fd, FIOPROTOHOOK, NULL); s = splimp (); /* paranoid; splnet probably ok */ if_down (&sc->sc_if); /* mark it down */ (void) close (sc->sc_fd); /* close the tty device */ for (;;) /* flush the wrt task queue and free mbufs */ { IF_DEQUEUE (&sc->sc_if.if_snd, pMbuf); if (pMbuf == NULL) break; m_freem (pMbuf); } if (sc->sc_wrtTaskId != ERROR) taskDelete (sc->sc_wrtTaskId); /* * Delete all routes associated with this SLIP interface. * This will effectively delete the point-to-point routes for this SLIP. */ (void) ifRouteDelete ("sl", unit); slSoftcFree (sc, unit); splx (s); return (OK); }/********************************************************************************* slSoftcFree - free the allocated sl_softc structure** This is called by slattach to free the allocated sl_softc structure* when error occurs within slattach. The reason for having this routine* is to get rid of the repetitive code within slattach ().* This routine is also called by slipDelete ().*/LOCAL void slSoftcFree ( SL_SOFTC *sc, int unit ) { /* Take the pointer to this SLIP interface out of the linked list * of all available network interfaces. The if_dettach () will un-do * the action taken by if_attach (). */ if_dettach (&sc->sc_if); semDelete (sc->sc_wrtSem); /* delete write semaphore */ if (sc->sc_buf) { (void) free (sc->sc_orig); sc->sc_buf = NULL; } (void) free ((char *) sc); sl_softc [unit] = (SL_SOFTC *) NULL; }/********************************************************************************* slinit - initialize SLIP interface*/LOCAL void slinit ( int unit ) { SL_SOFTC *sc = sl_softc [unit]; sc->sc_if.if_flags |= IFF_UP|IFF_RUNNING; /* open for business */ }/********************************************************************************* sloutput - output a packet over the SLIP line** Queue a packet and trigger the slipWrtTask if a packet is ready* by releasing the semaphore. CSLIP compression for TCP/IP headers is* supported if (enabled).** RETURNS: OK, or ERROR if the output queue is full.*/LOCAL STATUS sloutput ( FAST struct ifnet *ifp, /* SLIP interface pointer */ FAST struct mbuf *m, /* SLIP packet to be sent out */ struct sockaddr *dst, /* address of the destination */ struct rtentry *rtp /* pointer to the route entry */ ) { FAST SL_SOFTC *sc; FAST struct ip *ip; FAST int s; FAST int unit; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { m_freem (m); return (ENETDOWN); } /* * Check and see if protocol family is equal to AF_INET. * Currently only AF_INET is support for SLIP. */ if (dst->sa_family != AF_INET) { m_freem (m); return (EAFNOSUPPORT); } unit = ifp->if_unit; sc = sl_softc [unit]; /* * n.b.-- the `40' below checks that we have a least a min length * tcp/ip header contiguous in an mbuf. We don't do `sizeof' on * some struct because too many compilers add random padding. */ if (sc->sc_flags & SL_COMPRESS) /* compress enabled ? */ { ip = mtod(m, struct ip *); if ((ip->ip_p == IPPROTO_TCP) && (m->m_len >= 40)) *mtod(m, u_char *) |= sl_compress_tcp (m, ip, &sc->sc_comp, 1); } s = splimp (); /* * If send queue is full drop the packet. */ if (IF_QFULL (&ifp->if_snd)) { IF_DROP (&ifp->if_snd); m_freem (m); ++sc->sc_if.if_oerrors; splx (s); return (ENOBUFS); } /* enqueue the packet for IP module to read later */ IF_ENQUEUE (&ifp->if_snd, m); ifp->if_lastchange = tickGet (); splx (s); /* wake the SLIP ouput task to let it send out this packet */ semGive (sc->sc_wrtSem); return (OK); }/********************************************************************************* slipWrtTask - SLIP writer task** This is our write side task. It waits for a semaphore and* when sloutput() yields the semaphore, it will try to send out* the packet that's been queue up so far. Each SLIP interface* has its own slipWrtTask which is spawned in slipInit().* Start output on interface. Get another datagram* to send from the interface queue and map it to* the interface before starting output.** NOMANUAL*/void slipWrtTask ( FAST SL_SOFTC *sc /* SLIP softc pointer */ ) { FAST struct mbuf *m; FAST u_char *cp; FAST int len; int fd; struct mbuf *m2; int rdCount; int numch; char ch; int s; fd = sc->sc_fd; FOREVER { semTake (sc->sc_wrtSem, WAIT_FOREVER); /* sync w/ sloutput */ FOREVER { /* get a packet off of the queue */ s = splimp (); IF_DEQUEUE (&sc->sc_if.if_snd, m); splx (s); if (m == NULL) break; /* * Check if the serial line has been idle for awhile. * If it has been idle for awhile, we send out a FRAME_END * character to clear out any garbage in transit and start * fresh with a new packet. We find out whether or not * the line has been idle for awhile by looking at the * read side of the tty ring buffer queue. It is assumed * that if there is nothing to read from the queue, we * must have been idle for awhile. If our assumption * is incorrect, we only have wasted the amount of work * and bandwidth it takes to send a character over SLIP. * More than likely, though, this is better than sending * out a large packet and clobbering the whole packet * because of the bad data. */ (void) ioctl (fd, FIONREAD, (int) &rdCount); if (rdCount == 0) { ch = FRAME_END; ++sc->sc_if.if_obytes; (void) write (fd, &ch, 1); } /* * send the packet. */ while (m) { cp = mtod (m, u_char *); len = m->m_len; while (len > 0) { /* * Find out how many bytes in the string we can * handle without doing something special. */ if ((numch = numCharsToMask (FRAME_ESCAPE, FRAME_END, (u_int) len, cp)) > 0) { /* * Put numch characters at once * into the tty output queue. */ if (write (fd, (char *)cp, numch) != numch)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -