1 /* slip.c SLIP interface unit
3 * $Id: slip.c,v 1.11 1995/03/19 17:21:06 bdale Exp $
5 * Copyright 1991, Michael Westerhof, Sun Microsystems, Inc.
6 * This software may be freely used, distributed, or modified, providing
7 * this header is not removed.
12 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <netinet/in_systm.h>
17 #include <netinet/ip.h>
47 #include <sys/termio.h>
55 #define FNDELAY O_NDELAY
60 #define IF_NAME "slip" /* for use with the error checking macros */
63 * Define the special characters used by SLIP
72 * This is the routine that assembles a slip packet, and the private
73 * data structure we need to keep track of where we are.
76 static int assemble_slip();
78 unsigned char buffer[MAX_SIZE]; /* buffer from the serial line */
79 int bcount; /* number of total chars in buffer */
80 int bnext; /* next character to process */
81 unsigned char ipacket[MAX_SIZE]; /* the packet we are assembling */
82 int ifcount; /* total size of assembled packet */
83 int iescaped; /* flag set if we are escaped */
87 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
88 * open and initialize the IO interface. Return -1 for error.
89 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
92 struct interface *ifp;
106 CK_IFTYPE(ifp,IF_TYPE_SLIP);
108 if((ifp->status & IF_STAT_OPEN)) return 1;
111 /* BSDI cares about the modem control lines, so this won't ever
112 come back unless we do the open non-blocking, then set CLOCAL. */
113 ifp->fd = open(ifp->devname, O_RDWR | O_NONBLOCK);
115 ifp->fd = open(ifp->devname, O_RDWR);
122 if (fcntl(ifp->fd, F_SETFL, FNDELAY) < 0) {
123 PERR("setting non-blocking I/O on tty device");
128 #if defined(__bsdi__) || defined(linux)
129 if(tcgetattr(ifp->fd, &nterm)<0){
131 if(ioctl(ifp->fd, TCGETS, &nterm)<0){
132 #endif /* __bsdi__ */
135 if(ioctl(ifp->fd, TCGETA, &nterm)<0){
138 if(ioctl(ifp->fd, TIOCGETP, &nterm)<0){
140 PERR("fetching tty device parameters");
144 if(ifp->unit==50)baudrate=B50;
145 else if(ifp->unit==50)baudrate=B50;
146 else if(ifp->unit==75)baudrate=B75;
147 else if(ifp->unit==110)baudrate=B110;
148 else if(ifp->unit==134)baudrate=B134;
149 else if(ifp->unit==150)baudrate=B150;
150 else if(ifp->unit==200)baudrate=B200;
151 else if(ifp->unit==300)baudrate=B300;
152 else if(ifp->unit==600)baudrate=B600;
153 else if(ifp->unit==1200)baudrate=B1200;
154 else if(ifp->unit==1800)baudrate=B1800;
155 else if(ifp->unit==2400)baudrate=B2400;
156 else if(ifp->unit==4800)baudrate=B4800;
157 else if(ifp->unit==9600)baudrate=B9600;
159 else if(ifp->unit==19200)baudrate=B19200;
162 else if(ifp->unit==19200)baudrate=EXTA;
166 else if(ifp->unit==38400)baudrate=B38400;
169 else if(ifp->unit==38400)baudrate=EXTB;
172 else baudrate = B9600;
175 nterm.sg_flags = (RAW | ANYP);
176 nterm.sg_ispeed = baudrate;
177 nterm.sg_ospeed = baudrate;
181 nterm.c_cflag = baudrate | CS8 | CREAD | CLOCAL;
183 nterm.c_cc[VMIN] = 0;
184 nterm.c_cc[VTIME] = 0;
188 #if defined(__bsdi__) || defined(linux)
189 if(tcsetattr(ifp->fd, TCSANOW, &nterm)<0){
191 if(ioctl(ifp->fd, TCSETS, &nterm)<0){
192 #endif /* __bsdi__ */
195 if(ioctl(ifp->fd, TCSETA, &nterm)<0){
198 if(ioctl(ifp->fd, TIOCSETP, &nterm)<0){
200 PERR("setting tty device parameters");
204 if(ifp->private==NULL)ifp->private = malloc(sizeof(struct slippy));
205 if(ifp->private==NULL){
206 syslog(LOG_ERR,"cannot allocate private data structure (slip)");
210 (void)memset(ifp->private, 0, sizeof(struct slippy));
212 ifp->status = IF_STAT_OPEN;
217 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
218 * Read data from the specified interface. Return a complete IP datagram.
219 * If the datagram is not complete, then don't return anything.
220 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
222 int slip_read(ifp, m)
223 struct interface *ifp;
230 CK_IFTYPE(ifp,IF_TYPE_SLIP);
234 s = (struct slippy *)ifp->private;
235 ifp->status &= ~IF_STAT_CALL_AGAIN;
239 if(s->bnext >= s->bcount){ /* we need more data! */
242 n = read(ifp->fd, (char *)s->buffer, MAX_SIZE);
243 if(n==0)return 0; /* got nothing */
245 if(errno==EINTR)return 0; /* SIGHUP! */
246 if(errno==EWOULDBLOCK)return 0; /* got nothing */
247 PERR("read from tty device");
253 n = assemble_slip(s, s->buffer[s->bnext]);
257 (void)memcpy((char *)m->msg, (char *)s->ipacket, n);
259 if(s->bnext < s->bcount)
260 ifp->status |= IF_STAT_CALL_AGAIN;
267 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
268 * write data from to the specified interface. Return as soon as possible.
269 * The buffer provided will be a complete IP datagram.
270 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
273 #define SLIPEMIT(x) if(ofcount<MAX_SIZE*2){*ofptr=(x);ofptr++;ofcount++;}
275 int slip_send(ifp, m)
276 struct interface *ifp;
280 unsigned char opacket[MAX_SIZE*2], *ofptr, *mptr;
283 CK_IFTYPE(ifp,IF_TYPE_SLIP);
287 if(m->length<=0)return 0;
295 for(i=0;i<m->length;i++,mptr++){
299 }else if (*mptr==FESC){
310 * WARNING! It is possible for this write to actually write less data
311 * than expected if the system has, for example, no buffer space left.
312 * We ignore the error (just increment the write overrun counter),
313 * drop the current packet, and expect that the higher level protocols
316 * If we got an "interrupted system call" error we print the diagnostic
317 * and continue. (the packet gets dropped as above).
319 n = write(ifp->fd, (char *)opacket, ofcount);
321 syslog(LOG_ERR,"slip_send(): %s",strerror(errno));
322 if((errno==EINTR) || (errno==EAGAIN)) return 0;
325 if(n < ofcount)ifp->out_overruns++;
330 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
331 * take a character and assemble it into the buffer. Return the length
332 * of the completed packet, 0 if not yet completed. Packet can be found
333 * in the private buffer...
334 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
356 if(c==TFEND)c = FEND;
357 if(c==TFESC)c = FESC;
360 if(s->ifcount < MAX_SIZE){
361 s->ipacket[s->ifcount] = c;