📄 if_sl.c
字号:
break; sc->sc_if.if_obytes += numch; len -= numch; cp += numch; } /* * If there are characters left in the mbuf, * the first one must be special.. * Put it out in a different form. */ if (len) { ch = FRAME_ESCAPE; if (write (fd, &ch, 1) != 1) break; ++sc->sc_if.if_obytes; ch = (*cp == FRAME_ESCAPE) ? TRANS_FRAME_ESCAPE : TRANS_FRAME_END; if (write (fd, &ch, 1) != 1) break; ++sc->sc_if.if_obytes; ++cp; --len; } } m2 = m_free (m); m = m2; } /* * indicate the end-of-packet. */ ch = FRAME_END; if (write (fd, &ch, 1) != 1) { /* * This shouldn't happen but if it does we try one * more time (just for the hack of it) and increment * the if_collisions and if_oerrors. */ ch = FRAME_END; (void) write (fd, &ch, 1); sc->sc_if.if_collisions++; sc->sc_if.if_oerrors++; } else { ++sc->sc_if.if_obytes; sc->sc_if.if_opackets++; } } } }/********************************************************************************* slintr - SLIP tty protocol hook routine** Called at interrupt level by the tty driver input nterrupt routine.* It is our "protocol hook" routine set by an FIOPROTOHOOK ioctl() call.* slintr() examines each character coming in and keeps a count* of input characters in the ring buffer of the tty driver until* a full packet is indicated by FRAME_END.* When detected, enqueue a call to slread() via netJobAdd() to* be processed later at task level.* A net job will not be added if the first character of the packet* won't fit into the ring buffer. In that case the entire packet* must be discarded at interrupt level.** This routine will return FALSE to tyIRd() to indicate* that normal processing should continue within tyIRd() when* this routine returns.** RETURNS: FALSE so tyIRd continues processing*/LOCAL BOOL slintr ( int unit, /* SLIP unit number */ int inchar /* incoming character */ ) { FAST SL_SOFTC *sc = sl_softc [unit]; TY_DEV * pTyDev; RING_ID ringId; /* Set discard flag if this is a new packet and ring buffer full */ if ( sc->sc_qlen == 0 ) { pTyDev = (TY_DEV *) iosFdDevFind(sc->sc_fd); ringId = pTyDev->rdBuf; if (rngIsFull (ringId)) sc->sc_flags |= SL_INTR_PACKET_DISCARD; else sc->sc_flags &= ~SL_INTR_PACKET_DISCARD; } ++sc->sc_qlen; if ((inchar & 0xff) == FRAME_END || sc->sc_qlen == SLBUF_HI) { /* schedule a read for this packet */ if (sc->sc_flags & SL_INTR_PACKET_DISCARD) sc->sc_if.if_ierrors++; else { if (sc->sc_qlen == 1) /* Single FRAME_END character */ { sc->sc_qlen = 0; return (TRUE); /* Don't put it in ring buffer */ } else (void) netJobAdd ((FUNCPTR) slread, (int) sc, sc->sc_qlen, 0, 0, 0); } sc->sc_qlen = 0; } return (FALSE); /* continue ty processing */ }/********************************************************************************* slread - read a whole SLIP packet and call slinput to process each char** slread() is called only when FRAME_END is encountered when* we have a SLIP packet waiting for us to read in the tty's* input ring buffer.*/LOCAL void slread ( FAST SL_SOFTC *sc, /* SLIP interface */ FAST int count /* number of characters to be read */ ) { BOOL firstCluster = TRUE; char *builtCluster; char *nextBuf = sc->sc_buf; FAST u_char *c1 = (u_char *) sc->sc_buf; FAST u_char *c2 = c1; FAST u_char *end; int len; if ((len = read (sc->sc_fd, sc->sc_buf, count)) == 0) return; end = (u_char *) (sc->sc_buf + len); while (c1 < end) { ++sc->sc_if.if_ibytes; /* increment the recieved bytes */ if (sc->sc_ilen > sc->sc_if.if_mtu) { sc->sc_if.if_ierrors++; break; } switch (*c1) { case FRAME_END: { if (sc->sc_ilen > 0) { if ((builtCluster = slRecv (sc, firstCluster)) != NULL) { nextBuf = builtCluster; firstCluster = FALSE; } sc->sc_ilen = 0; } sc->sc_buf = (char *) ++c1; c2 = c1; break; } case FRAME_ESCAPE: { c1++; if (*c1 == TRANS_FRAME_ESCAPE) *c1 = FRAME_ESCAPE; else if (*c1 == TRANS_FRAME_END) *c1 = FRAME_END; else { sc->sc_if.if_ierrors++; sc->sc_ilen = 0; sc->sc_buf = (char *) c1; c2 = c1; break; } } default: { sc->sc_ilen++; *c2++ = *c1++; } } } sc->sc_buf = nextBuf; sc->sc_ilen = 0; }/********************************************************************************* slRecv - process an input frame** This routine processes an input frame, then passes it up to the higher* level in a form it expects. Buffer loaning, etherInputHookRtns, and* CSLIP uncompression are all supported. Trailer protocols are not supported.** RETURNS: N/A*/LOCAL char *slRecv ( FAST SL_SOFTC *sc, /* SLIP interface */ BOOL firstCluster ) { FAST struct mbuf *m = NULL; FAST char type; char *nextBuf = NULL; char *origBuf = sc->sc_buf; UINT8 *origRef = sc->sc_pRefC[(sc->sc_nLoanRxBuf - 1)]; int s; type = *sc->sc_buf & 0xf0; if (type != (IPVERSION << 4)) { if (type & 0x80) type = TYPE_COMPRESSED_TCP; else if (type == TYPE_UNCOMPRESSED_TCP) *sc->sc_buf &= 0x4f; /* * we've got something that's not an IP packet. * If compression is enabled, try to uncompress * it. Otherwise, if `auto-enable' compression * is on and it's a reasonable packet, * uncompress it then enable compression. * Otherwise, drop it. */ if ((sc->sc_flags & SL_COMPRESS) || ((sc->sc_flags & SL_COMPRESS_RX) && (type == TYPE_UNCOMPRESSED_TCP) && (sc->sc_ilen >= 40))) { if ((sc->sc_ilen = sl_uncompress_tcp ((u_char **)&sc->sc_buf, sc->sc_ilen, (u_int) type, &sc->sc_comp)) <= 0) { sc->sc_if.if_ierrors++; return (NULL); } sc->sc_flags |= SL_COMPRESS; } else { sc->sc_if.if_ierrors++; return (NULL); } } if ((etherInputHookRtn != NULL) && ((*etherInputHookRtn) (&sc->sc_if, sc->sc_buf, sc->sc_ilen) != 0)) return (NULL); if ((firstCluster) && (sc->sc_nLoanRxBuf > 0) && (USE_CLUSTER (sc->sc_ilen))) m = build_cluster (sc->sc_buf, sc->sc_ilen, &sc->sc_if, MC_SL, sc->sc_pRefC[(sc->sc_nLoanRxBuf - 1)], slLoanFree, (int) sc, (int) origBuf, (int) origRef); /* if buffer was successfully turned into mbuf cluster */ if (m != NULL) nextBuf = sc->sc_lPool[--sc->sc_nLoanRxBuf]; else { /* else do same ol' copy to mbuf */ m = copy_to_mbufs (sc->sc_buf, sc->sc_ilen, 0, &sc->sc_if); if (m == NULL) { sc->sc_if.if_ierrors++; return (NULL); } } /* send up to protocol */ sc->sc_if.if_ipackets++; sc->sc_if.if_lastchange = tickGet(); s = splimp(); if (IF_QFULL(&ipintrq)) { IF_DROP(&ipintrq); sc->sc_if.if_ierrors++; sc->sc_if.if_iqdrops++; m_freem(m); } else { IF_ENQUEUE(&ipintrq, m); schednetisr(NETISR_IP); } splx(s); return (nextBuf); }/********************************************************************************* slioctl - SLIP ioctl routine** Process an ioctl request.** RETURNS: 0 or errno*/LOCAL int slioctl ( FAST struct ifnet *ifp, /* pointer to SLIP interface */ int cmd, /* command */ caddr_t data /* data */ ) { FAST struct ifaddr * ifa = (struct ifaddr *)data; FAST struct ifreq * ifr; int error = 0; int s; s = splimp (); switch (cmd) { case SIOCGIFFLAGS: *(short *)data = ifp->if_flags; break; case SIOCSIFADDR: if (ifa->ifa_addr->sa_family == AF_INET) { slinit (ifp->if_unit); ifa->ifa_rtrequest = slRtRequest; } else error = EAFNOSUPPORT; break; case SIOCSIFDSTADDR: if (ifa->ifa_dstaddr->sa_family != AF_INET) error = EAFNOSUPPORT; break; case SIOCADDMULTI: case SIOCDELMULTI: ifr = (struct ifreq *)data; if (ifr == 0) { error = EAFNOSUPPORT; /* XXX */ break; } switch (ifr->ifr_addr.sa_family) {#ifdef INET case AF_INET: break;#endif default: error = EAFNOSUPPORT; break; } break; default: error = EINVAL; } splx (s); return (error); }/********************************************************************************* numCharsToMask - scan the buffer for a mask** numcharsToMask finds out how many characters are in a string* before a character that matches the 'mask'.** RETURNS: number of chars up to the mask*/LOCAL int numCharsToMask ( FAST u_char mask1, FAST u_char mask2, u_int size, FAST u_char *cp ) { FAST u_char *end = &cp [size]; u_char *start = cp; while ((cp < end) && (*cp != mask1) && (*cp != mask2)) cp++; return (cp - start); }/********************************************************************************* slLoanFree - return the given buffer to loaner pool** This routine returns <pRxBuf> to the pool of available loaner buffers.* It also returns <pRef> to the pool of available loaner reference counters,* then zeroes the reference count.** RETURNS: N/A*/ LOCAL void slLoanFree ( SL_SOFTC *sc, char *pRxBuf, UINT8 *pRef ) { /* return loaned buffer to pool */ sc->sc_lPool[sc->sc_nLoanRxBuf] = pRxBuf; /* return loaned reference count to pool */ sc->sc_pRefC[sc->sc_nLoanRxBuf++] = pRef; /* reset reference count - should have been done from above, but... */ *pRef = 0; }/********************************************************************************* slRtRequest - perform special routing.** This function performs special processing when adding a route to itself* on a slip interface. It intializes the interface pointer to the loop back* so that the packet can be rerouted through the loopback instead of actually* sending the packet out on the wire and have the other end loop back the* packet. The capability can be turned off by intializing the global flag* slipLoopBack to 0. By default it is turned on. ** NOMANUAL** RETURNS: N/A*/static void slRtRequest ( int cmd, /* route command */ struct rtentry * pRtEntry, /* pointer to the route entry */ struct sockaddr * pSockAddr /* pointer to the sock addr */ ) { /* only when adding a route to itself */ if (cmd == RTM_ADD) { if (slipLoopBack && (pRtEntry->rt_flags & RTF_HOST) && (SIN(rt_key(pRtEntry))->sin_addr.s_addr == (IA_SIN(pRtEntry->rt_ifa))->sin_addr.s_addr)) { pRtEntry->rt_rmx.rmx_expire = 0; pRtEntry->rt_ifp = &loif; /* initialize to the loop back */ } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -