blob: 899c4a2112c9f7ff1cb5f8e8f5ed953ff71f1582 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * slip.c This module implements the SLIP protocol for kernel-based
3 * devices like TTY. It interfaces between a raw TTY, and the
4 * kernel's INET protocol layers.
5 *
6 * Version: @(#)slip.c 0.8.3 12/24/94
7 *
8 * Authors: Laurence Culhane, <loz@holmes.demon.co.uk>
9 * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
10 *
11 * Fixes:
12 * Alan Cox : Sanity checks and avoid tx overruns.
13 * Has a new sl->mtu field.
Alan Cox9ce6cf22007-11-19 15:03:38 +000014 * Alan Cox : Found cause of overrun. ifconfig sl0
15 * mtu upwards. Driver now spots this
16 * and grows/shrinks its buffers(hack!).
17 * Memory leak if you run out of memory
18 * setting up a slip driver fixed.
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 * Matt Dillon : Printable slip (borrowed from NET2E)
20 * Pauline Middelink : Slip driver fixes.
21 * Alan Cox : Honours the old SL_COMPRESSED flag
22 * Alan Cox : KISS AX.25 and AXUI IP support
23 * Michael Riepe : Automatic CSLIP recognition added
24 * Charles Hedrick : CSLIP header length problem fix.
25 * Alan Cox : Corrected non-IP cases of the above.
26 * Alan Cox : Now uses hardware type as per FvK.
27 * Alan Cox : Default to 192.168.0.0 (RFC 1597)
28 * A.N.Kuznetsov : dev_tint() recursion fix.
29 * Dmitry Gorodchanin : SLIP memory leaks
30 * Dmitry Gorodchanin : Code cleanup. Reduce tty driver
31 * buffering from 4096 to 256 bytes.
32 * Improving SLIP response time.
33 * CONFIG_SLIP_MODE_SLIP6.
Alan Cox9ce6cf22007-11-19 15:03:38 +000034 * ifconfig sl? up & down now works
35 * correctly.
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 * Modularization.
37 * Alan Cox : Oops - fix AX.25 buffer lengths
38 * Dmitry Gorodchanin : Even more cleanups. Preserve CSLIP
39 * statistics. Include CSLIP code only
40 * if it really needed.
41 * Alan Cox : Free slhc buffers in the right place.
42 * Alan Cox : Allow for digipeated IP over AX.25
43 * Matti Aarnio : Dynamic SLIP devices, with ideas taken
44 * from Jim Freeman's <jfree@caldera.com>
45 * dynamic PPP devices. We do NOT kfree()
46 * device entries, just reg./unreg. them
47 * as they are needed. We kfree() them
48 * at module cleanup.
Alan Cox9ce6cf22007-11-19 15:03:38 +000049 * With MODULE-loading ``insmod'', user
50 * can issue parameter: slip_maxdev=1024
51 * (Or how much he/she wants.. Default
52 * is 256)
53 * Stanislav Voronyi : Slip line checking, with ideas taken
54 * from multislip BSDI driver which was
55 * written by Igor Chechik, RELCOM Corp.
56 * Only algorithms have been ported to
57 * Linux SLIP driver.
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 * Vitaly E. Lavrov : Sane behaviour on tty hangup.
Alan Cox9ce6cf22007-11-19 15:03:38 +000059 * Alexey Kuznetsov : Cleanup interfaces to tty & netdevice
60 * modules.
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 */
62
63#define SL_CHECK_TRANSMIT
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#include <linux/module.h>
65#include <linux/moduleparam.h>
66
67#include <asm/system.h>
68#include <asm/uaccess.h>
69#include <linux/bitops.h>
70#include <linux/string.h>
71#include <linux/mm.h>
72#include <linux/interrupt.h>
73#include <linux/in.h>
74#include <linux/tty.h>
75#include <linux/errno.h>
76#include <linux/netdevice.h>
77#include <linux/etherdevice.h>
78#include <linux/skbuff.h>
79#include <linux/rtnetlink.h>
80#include <linux/if_arp.h>
81#include <linux/if_slip.h>
David S. Miller12dc2fd2005-06-28 16:27:32 -070082#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070083#include <linux/init.h>
84#include "slip.h"
85#ifdef CONFIG_INET
86#include <linux/ip.h>
87#include <linux/tcp.h>
88#include <net/slhc_vj.h>
89#endif
90
91#define SLIP_VERSION "0.8.4-NET3.019-NEWTTY"
92
93static struct net_device **slip_devs;
94
95static int slip_maxdev = SL_NRUNIT;
96module_param(slip_maxdev, int, 0);
97MODULE_PARM_DESC(slip_maxdev, "Maximum number of slip devices");
98
99static int slip_esc(unsigned char *p, unsigned char *d, int len);
100static void slip_unesc(struct slip *sl, unsigned char c);
101#ifdef CONFIG_SLIP_MODE_SLIP6
102static int slip_esc6(unsigned char *p, unsigned char *d, int len);
103static void slip_unesc6(struct slip *sl, unsigned char c);
104#endif
105#ifdef CONFIG_SLIP_SMART
106static void sl_keepalive(unsigned long sls);
107static void sl_outfill(unsigned long sls);
Alan Cox9ce6cf22007-11-19 15:03:38 +0000108static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109#endif
110
111/********************************
112* Buffer administration routines:
113* sl_alloc_bufs()
114* sl_free_bufs()
115* sl_realloc_bufs()
116*
117* NOTE: sl_realloc_bufs != sl_free_bufs + sl_alloc_bufs, because
118* sl_realloc_bufs provides strong atomicity and reallocation
119* on actively running device.
120*********************************/
121
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400122/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 Allocate channel buffers.
124 */
125
Alan Cox9ce6cf22007-11-19 15:03:38 +0000126static int sl_alloc_bufs(struct slip *sl, int mtu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
128 int err = -ENOBUFS;
129 unsigned long len;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000130 char *rbuff = NULL;
131 char *xbuff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132#ifdef SL_INCLUDE_CSLIP
Alan Cox9ce6cf22007-11-19 15:03:38 +0000133 char *cbuff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 struct slcompress *slcomp = NULL;
135#endif
136
137 /*
138 * Allocate the SLIP frame buffers:
139 *
140 * rbuff Receive buffer.
141 * xbuff Transmit buffer.
142 * cbuff Temporary compression buffer.
143 */
144 len = mtu * 2;
145
146 /*
147 * allow for arrival of larger UDP packets, even if we say not to
148 * also fixes a bug in which SunOS sends 512-byte packets even with
149 * an MSS of 128
150 */
151 if (len < 576 * 2)
152 len = 576 * 2;
153 rbuff = kmalloc(len + 4, GFP_KERNEL);
154 if (rbuff == NULL)
155 goto err_exit;
156 xbuff = kmalloc(len + 4, GFP_KERNEL);
157 if (xbuff == NULL)
158 goto err_exit;
159#ifdef SL_INCLUDE_CSLIP
160 cbuff = kmalloc(len + 4, GFP_KERNEL);
161 if (cbuff == NULL)
162 goto err_exit;
163 slcomp = slhc_init(16, 16);
164 if (slcomp == NULL)
165 goto err_exit;
166#endif
167 spin_lock_bh(&sl->lock);
168 if (sl->tty == NULL) {
169 spin_unlock_bh(&sl->lock);
170 err = -ENODEV;
171 goto err_exit;
172 }
173 sl->mtu = mtu;
174 sl->buffsize = len;
175 sl->rcount = 0;
176 sl->xleft = 0;
177 rbuff = xchg(&sl->rbuff, rbuff);
178 xbuff = xchg(&sl->xbuff, xbuff);
179#ifdef SL_INCLUDE_CSLIP
180 cbuff = xchg(&sl->cbuff, cbuff);
181 slcomp = xchg(&sl->slcomp, slcomp);
182#ifdef CONFIG_SLIP_MODE_SLIP6
183 sl->xdata = 0;
184 sl->xbits = 0;
185#endif
186#endif
187 spin_unlock_bh(&sl->lock);
188 err = 0;
189
190 /* Cleanup */
191err_exit:
192#ifdef SL_INCLUDE_CSLIP
Jesper Juhl158a0e42005-04-24 18:59:30 -0700193 kfree(cbuff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 if (slcomp)
195 slhc_free(slcomp);
196#endif
Jesper Juhl158a0e42005-04-24 18:59:30 -0700197 kfree(xbuff);
198 kfree(rbuff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 return err;
200}
201
202/* Free a SLIP channel buffers. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000203static void sl_free_bufs(struct slip *sl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 /* Free all SLIP frame buffers. */
Jesper Juhl9b200b02005-06-23 21:06:56 -0700206 kfree(xchg(&sl->rbuff, NULL));
207 kfree(xchg(&sl->xbuff, NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208#ifdef SL_INCLUDE_CSLIP
Jesper Juhl9b200b02005-06-23 21:06:56 -0700209 kfree(xchg(&sl->cbuff, NULL));
210 slhc_free(xchg(&sl->slcomp, NULL));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211#endif
212}
213
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400214/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 Reallocate slip channel buffers.
216 */
217
218static int sl_realloc_bufs(struct slip *sl, int mtu)
219{
220 int err = 0;
221 struct net_device *dev = sl->dev;
222 unsigned char *xbuff, *rbuff;
223#ifdef SL_INCLUDE_CSLIP
224 unsigned char *cbuff;
225#endif
226 int len = mtu * 2;
227
228/*
229 * allow for arrival of larger UDP packets, even if we say not to
230 * also fixes a bug in which SunOS sends 512-byte packets even with
231 * an MSS of 128
232 */
233 if (len < 576 * 2)
234 len = 576 * 2;
235
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800236 xbuff = kmalloc(len + 4, GFP_ATOMIC);
237 rbuff = kmalloc(len + 4, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238#ifdef SL_INCLUDE_CSLIP
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800239 cbuff = kmalloc(len + 4, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240#endif
241
242
243#ifdef SL_INCLUDE_CSLIP
244 if (xbuff == NULL || rbuff == NULL || cbuff == NULL) {
245#else
246 if (xbuff == NULL || rbuff == NULL) {
247#endif
248 if (mtu >= sl->mtu) {
249 printk(KERN_WARNING "%s: unable to grow slip buffers, MTU change cancelled.\n",
250 dev->name);
251 err = -ENOBUFS;
252 }
253 goto done;
254 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 spin_lock_bh(&sl->lock);
256
257 err = -ENODEV;
258 if (sl->tty == NULL)
259 goto done_on_bh;
260
261 xbuff = xchg(&sl->xbuff, xbuff);
262 rbuff = xchg(&sl->rbuff, rbuff);
263#ifdef SL_INCLUDE_CSLIP
264 cbuff = xchg(&sl->cbuff, cbuff);
265#endif
266 if (sl->xleft) {
267 if (sl->xleft <= len) {
268 memcpy(sl->xbuff, sl->xhead, sl->xleft);
269 } else {
270 sl->xleft = 0;
271 sl->tx_dropped++;
272 }
273 }
274 sl->xhead = sl->xbuff;
275
276 if (sl->rcount) {
277 if (sl->rcount <= len) {
278 memcpy(sl->rbuff, rbuff, sl->rcount);
279 } else {
280 sl->rcount = 0;
281 sl->rx_over_errors++;
282 set_bit(SLF_ERROR, &sl->flags);
283 }
284 }
285 sl->mtu = mtu;
286 dev->mtu = mtu;
287 sl->buffsize = len;
288 err = 0;
289
290done_on_bh:
291 spin_unlock_bh(&sl->lock);
292
293done:
Jesper Juhl158a0e42005-04-24 18:59:30 -0700294 kfree(xbuff);
295 kfree(rbuff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296#ifdef SL_INCLUDE_CSLIP
Jesper Juhl158a0e42005-04-24 18:59:30 -0700297 kfree(cbuff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298#endif
299 return err;
300}
301
302
303/* Set the "sending" flag. This must be atomic hence the set_bit. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000304static inline void sl_lock(struct slip *sl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305{
306 netif_stop_queue(sl->dev);
307}
308
309
310/* Clear the "sending" flag. This must be atomic, hence the ASM. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000311static inline void sl_unlock(struct slip *sl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312{
313 netif_wake_queue(sl->dev);
314}
315
316/* Send one completely decapsulated IP datagram to the IP layer. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000317static void sl_bump(struct slip *sl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
319 struct sk_buff *skb;
320 int count;
321
322 count = sl->rcount;
323#ifdef SL_INCLUDE_CSLIP
324 if (sl->mode & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000325 unsigned char c = sl->rbuff[0];
326 if (c & SL_TYPE_COMPRESSED_TCP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 /* ignore compressed packets when CSLIP is off */
328 if (!(sl->mode & SL_MODE_CSLIP)) {
329 printk(KERN_WARNING "%s: compressed packet ignored\n", sl->dev->name);
330 return;
331 }
Alan Cox9ce6cf22007-11-19 15:03:38 +0000332 /* make sure we've reserved enough space for uncompress
333 to use */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 if (count + 80 > sl->buffsize) {
335 sl->rx_over_errors++;
336 return;
337 }
338 count = slhc_uncompress(sl->slcomp, sl->rbuff, count);
Alan Cox9ce6cf22007-11-19 15:03:38 +0000339 if (count <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
342 if (!(sl->mode & SL_MODE_CSLIP)) {
343 /* turn on header compression */
344 sl->mode |= SL_MODE_CSLIP;
345 sl->mode &= ~SL_MODE_ADAPTIVE;
346 printk(KERN_INFO "%s: header compression turned on\n", sl->dev->name);
347 }
348 sl->rbuff[0] &= 0x4f;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000349 if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 }
352 }
353#endif /* SL_INCLUDE_CSLIP */
354
Alan Cox9ce6cf22007-11-19 15:03:38 +0000355 sl->rx_bytes += count;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400356
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 skb = dev_alloc_skb(count);
Alan Cox9ce6cf22007-11-19 15:03:38 +0000358 if (skb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name);
360 sl->rx_dropped++;
361 return;
362 }
363 skb->dev = sl->dev;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000364 memcpy(skb_put(skb, count), sl->rbuff, count);
Arnaldo Carvalho de Melo98e399f2007-03-19 15:33:04 -0700365 skb_reset_mac_header(skb);
Alan Cox9ce6cf22007-11-19 15:03:38 +0000366 skb->protocol = htons(ETH_P_IP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 netif_rx(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 sl->rx_packets++;
369}
370
371/* Encapsulate one IP datagram and stuff into a TTY queue. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000372static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373{
374 unsigned char *p;
375 int actual, count;
376
377 if (len > sl->mtu) { /* Sigh, shouldn't occur BUT ... */
378 printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name);
379 sl->tx_dropped++;
380 sl_unlock(sl);
381 return;
382 }
383
384 p = icp;
385#ifdef SL_INCLUDE_CSLIP
Alan Cox9ce6cf22007-11-19 15:03:38 +0000386 if (sl->mode & SL_MODE_CSLIP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 len = slhc_compress(sl->slcomp, p, len, sl->cbuff, &p, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388#endif
389#ifdef CONFIG_SLIP_MODE_SLIP6
Alan Cox9ce6cf22007-11-19 15:03:38 +0000390 if (sl->mode & SL_MODE_SLIP6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 count = slip_esc6(p, (unsigned char *) sl->xbuff, len);
392 else
393#endif
394 count = slip_esc(p, (unsigned char *) sl->xbuff, len);
395
396 /* Order of next two lines is *very* important.
397 * When we are sending a little amount of data,
Alan Coxf34d7a52008-04-30 00:54:13 -0700398 * the transfer may be completed inside the ops->write()
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 * routine, because it's running with interrupts enabled.
400 * In this case we *never* got WRITE_WAKEUP event,
401 * if we did not request it before write operation.
402 * 14 Oct 1994 Dmitry Gorodchanin.
403 */
Alan Cox8a1ec212008-12-05 22:31:52 -0800404 set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
Alan Coxf34d7a52008-04-30 00:54:13 -0700405 actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406#ifdef SL_CHECK_TRANSMIT
407 sl->dev->trans_start = jiffies;
408#endif
409 sl->xleft = count - actual;
410 sl->xhead = sl->xbuff + actual;
411#ifdef CONFIG_SLIP_SMART
412 /* VSV */
413 clear_bit(SLF_OUTWAIT, &sl->flags); /* reset outfill flag */
414#endif
415}
416
417/*
418 * Called by the driver when there's room for more data. If we have
419 * more packets to send, we send them here.
420 */
421static void slip_write_wakeup(struct tty_struct *tty)
422{
423 int actual;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000424 struct slip *sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
426 /* First make sure we're connected. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000427 if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 return;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000429
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 if (sl->xleft <= 0) {
431 /* Now serial buffer is almost free & we can start
432 * transmission of another packet */
433 sl->tx_packets++;
Alan Cox8a1ec212008-12-05 22:31:52 -0800434 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 sl_unlock(sl);
436 return;
437 }
438
Alan Coxf34d7a52008-04-30 00:54:13 -0700439 actual = tty->ops->write(tty, sl->xhead, sl->xleft);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 sl->xleft -= actual;
441 sl->xhead += actual;
442}
443
444static void sl_tx_timeout(struct net_device *dev)
445{
446 struct slip *sl = netdev_priv(dev);
447
448 spin_lock(&sl->lock);
449
450 if (netif_queue_stopped(dev)) {
451 if (!netif_running(dev))
452 goto out;
453
454 /* May be we must check transmitter timeout here ?
455 * 14 Oct 1994 Dmitry Gorodchanin.
456 */
457#ifdef SL_CHECK_TRANSMIT
458 if (time_before(jiffies, dev->trans_start + 20 * HZ)) {
459 /* 20 sec timeout not reached */
460 goto out;
461 }
Alan Cox9ce6cf22007-11-19 15:03:38 +0000462 printk(KERN_WARNING "%s: transmit timed out, %s?\n",
463 dev->name,
Alan Coxf34d7a52008-04-30 00:54:13 -0700464 (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
Alan Cox9ce6cf22007-11-19 15:03:38 +0000465 "bad line quality" : "driver error");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 sl->xleft = 0;
Alan Cox8a1ec212008-12-05 22:31:52 -0800467 clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 sl_unlock(sl);
469#endif
470 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471out:
472 spin_unlock(&sl->lock);
473}
474
475
476/* Encapsulate an IP datagram and kick it into a TTY queue. */
477static int
478sl_xmit(struct sk_buff *skb, struct net_device *dev)
479{
480 struct slip *sl = netdev_priv(dev);
481
482 spin_lock(&sl->lock);
Alan Cox9ce6cf22007-11-19 15:03:38 +0000483 if (!netif_running(dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 spin_unlock(&sl->lock);
485 printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
486 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000487 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 }
489 if (sl->tty == NULL) {
490 spin_unlock(&sl->lock);
491 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000492 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 }
494
495 sl_lock(sl);
Alan Cox9ce6cf22007-11-19 15:03:38 +0000496 sl->tx_bytes += skb->len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 sl_encaps(sl, skb->data, skb->len);
498 spin_unlock(&sl->lock);
499
500 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000501 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502}
503
504
505/******************************************
506 * Routines looking at netdevice side.
507 ******************************************/
508
509/* Netdevice UP -> DOWN routine */
510
511static int
512sl_close(struct net_device *dev)
513{
514 struct slip *sl = netdev_priv(dev);
515
516 spin_lock_bh(&sl->lock);
Alan Cox8a1ec212008-12-05 22:31:52 -0800517 if (sl->tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 /* TTY discipline is running. */
Alan Cox8a1ec212008-12-05 22:31:52 -0800519 clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 netif_stop_queue(dev);
521 sl->rcount = 0;
522 sl->xleft = 0;
523 spin_unlock_bh(&sl->lock);
524
525 return 0;
526}
527
528/* Netdevice DOWN -> UP routine */
529
530static int sl_open(struct net_device *dev)
531{
532 struct slip *sl = netdev_priv(dev);
533
Alan Cox9ce6cf22007-11-19 15:03:38 +0000534 if (sl->tty == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 return -ENODEV;
536
537 sl->flags &= (1 << SLF_INUSE);
538 netif_start_queue(dev);
539 return 0;
540}
541
542/* Netdevice change MTU request */
543
544static int sl_change_mtu(struct net_device *dev, int new_mtu)
545{
546 struct slip *sl = netdev_priv(dev);
547
548 if (new_mtu < 68 || new_mtu > 65534)
549 return -EINVAL;
550
551 if (new_mtu != dev->mtu)
552 return sl_realloc_bufs(sl, new_mtu);
553 return 0;
554}
555
556/* Netdevice get statistics request */
557
558static struct net_device_stats *
559sl_get_stats(struct net_device *dev)
560{
561 static struct net_device_stats stats;
562 struct slip *sl = netdev_priv(dev);
563#ifdef SL_INCLUDE_CSLIP
564 struct slcompress *comp;
565#endif
566
567 memset(&stats, 0, sizeof(struct net_device_stats));
568
569 stats.rx_packets = sl->rx_packets;
570 stats.tx_packets = sl->tx_packets;
571 stats.rx_bytes = sl->rx_bytes;
572 stats.tx_bytes = sl->tx_bytes;
573 stats.rx_dropped = sl->rx_dropped;
574 stats.tx_dropped = sl->tx_dropped;
575 stats.tx_errors = sl->tx_errors;
576 stats.rx_errors = sl->rx_errors;
577 stats.rx_over_errors = sl->rx_over_errors;
578#ifdef SL_INCLUDE_CSLIP
579 stats.rx_fifo_errors = sl->rx_compressed;
580 stats.tx_fifo_errors = sl->tx_compressed;
581 stats.collisions = sl->tx_misses;
582 comp = sl->slcomp;
583 if (comp) {
584 stats.rx_fifo_errors += comp->sls_i_compressed;
585 stats.rx_dropped += comp->sls_i_tossed;
586 stats.tx_fifo_errors += comp->sls_o_compressed;
587 stats.collisions += comp->sls_o_misses;
588 }
589#endif /* CONFIG_INET */
590 return (&stats);
591}
592
593/* Netdevice register callback */
594
595static int sl_init(struct net_device *dev)
596{
597 struct slip *sl = netdev_priv(dev);
598
599 /*
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400600 * Finish setting up the DEVICE info.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 */
602
603 dev->mtu = sl->mtu;
604 dev->type = ARPHRD_SLIP + sl->mode;
605#ifdef SL_CHECK_TRANSMIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 dev->watchdog_timeo = 20*HZ;
607#endif
608 return 0;
609}
610
611
612static void sl_uninit(struct net_device *dev)
613{
614 struct slip *sl = netdev_priv(dev);
615
616 sl_free_bufs(sl);
617}
618
Stephen Hemmingerb1da6832009-01-07 18:09:36 -0800619static const struct net_device_ops sl_netdev_ops = {
620 .ndo_init = sl_init,
621 .ndo_uninit = sl_uninit,
622 .ndo_open = sl_open,
623 .ndo_stop = sl_close,
624 .ndo_start_xmit = sl_xmit,
625 .ndo_get_stats = sl_get_stats,
626 .ndo_change_mtu = sl_change_mtu,
627 .ndo_tx_timeout = sl_tx_timeout,
628#ifdef CONFIG_SLIP_SMART
629 .ndo_do_ioctl = sl_ioctl,
630#endif
631};
632
633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634static void sl_setup(struct net_device *dev)
635{
Stephen Hemmingerb1da6832009-01-07 18:09:36 -0800636 dev->netdev_ops = &sl_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 dev->destructor = free_netdev;
Stephen Hemmingerb1da6832009-01-07 18:09:36 -0800638
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 dev->hard_header_len = 0;
640 dev->addr_len = 0;
641 dev->tx_queue_len = 10;
642
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 /* New-style flags. */
644 dev->flags = IFF_NOARP|IFF_POINTOPOINT|IFF_MULTICAST;
645}
646
647/******************************************
648 Routines looking at TTY side.
649 ******************************************/
650
651
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652/*
653 * Handle the 'receiver data ready' interrupt.
654 * This function is called by the 'tty_io' module in the kernel when
655 * a block of SLIP data has been received, which can now be decapsulated
656 * and sent on to some IP layer for further processing. This will not
657 * be re-entered while running but other ldisc functions may be called
658 * in parallel
659 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400660
Alan Cox9ce6cf22007-11-19 15:03:38 +0000661static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp,
662 char *fp, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663{
Alan Cox9ce6cf22007-11-19 15:03:38 +0000664 struct slip *sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
Alan Cox9ce6cf22007-11-19 15:03:38 +0000666 if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 return;
668
669 /* Read the characters out of the buffer */
670 while (count--) {
671 if (fp && *fp++) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000672 if (!test_and_set_bit(SLF_ERROR, &sl->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 sl->rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 cp++;
675 continue;
676 }
677#ifdef CONFIG_SLIP_MODE_SLIP6
678 if (sl->mode & SL_MODE_SLIP6)
679 slip_unesc6(sl, *cp++);
680 else
681#endif
682 slip_unesc(sl, *cp++);
683 }
684}
685
686/************************************
687 * slip_open helper routines.
688 ************************************/
689
690/* Collect hanged up channels */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691static void sl_sync(void)
692{
693 int i;
694 struct net_device *dev;
695 struct slip *sl;
696
697 for (i = 0; i < slip_maxdev; i++) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000698 dev = slip_devs[i];
699 if (dev == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 break;
701
702 sl = netdev_priv(dev);
703 if (sl->tty || sl->leased)
704 continue;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000705 if (dev->flags & IFF_UP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 dev_close(dev);
707 }
708}
709
710
711/* Find a free SLIP channel, and link in this `tty' line. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000712static struct slip *sl_alloc(dev_t line)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713{
714 int i;
715 int sel = -1;
716 int score = -1;
717 struct net_device *dev = NULL;
718 struct slip *sl;
719
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400720 if (slip_devs == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 return NULL; /* Master array missing ! */
722
723 for (i = 0; i < slip_maxdev; i++) {
724 dev = slip_devs[i];
725 if (dev == NULL)
726 break;
727
728 sl = netdev_priv(dev);
729 if (sl->leased) {
730 if (sl->line != line)
731 continue;
732 if (sl->tty)
733 return NULL;
734
735 /* Clear ESCAPE & ERROR flags */
736 sl->flags &= (1 << SLF_INUSE);
737 return sl;
738 }
739
740 if (sl->tty)
741 continue;
742
743 if (current->pid == sl->pid) {
744 if (sl->line == line && score < 3) {
745 sel = i;
746 score = 3;
747 continue;
748 }
749 if (score < 2) {
750 sel = i;
751 score = 2;
752 }
753 continue;
754 }
755 if (sl->line == line && score < 1) {
756 sel = i;
757 score = 1;
758 continue;
759 }
760 if (score < 0) {
761 sel = i;
762 score = 0;
763 }
764 }
765
766 if (sel >= 0) {
767 i = sel;
768 dev = slip_devs[i];
769 if (score > 1) {
770 sl = netdev_priv(dev);
771 sl->flags &= (1 << SLF_INUSE);
772 return sl;
773 }
774 }
775
776 /* Sorry, too many, all slots in use */
777 if (i >= slip_maxdev)
778 return NULL;
779
780 if (dev) {
781 sl = netdev_priv(dev);
782 if (test_bit(SLF_INUSE, &sl->flags)) {
783 unregister_netdevice(dev);
784 dev = NULL;
785 slip_devs[i] = NULL;
786 }
787 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400788
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 if (!dev) {
790 char name[IFNAMSIZ];
791 sprintf(name, "sl%d", i);
792
793 dev = alloc_netdev(sizeof(*sl), name, sl_setup);
794 if (!dev)
795 return NULL;
796 dev->base_addr = i;
797 }
798
799 sl = netdev_priv(dev);
800
801 /* Initialize channel control data */
802 sl->magic = SLIP_MAGIC;
803 sl->dev = dev;
804 spin_lock_init(&sl->lock);
805 sl->mode = SL_MODE_DEFAULT;
806#ifdef CONFIG_SLIP_SMART
Alan Cox9ce6cf22007-11-19 15:03:38 +0000807 /* initialize timer_list struct */
808 init_timer(&sl->keepalive_timer);
809 sl->keepalive_timer.data = (unsigned long)sl;
810 sl->keepalive_timer.function = sl_keepalive;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 init_timer(&sl->outfill_timer);
Alan Cox9ce6cf22007-11-19 15:03:38 +0000812 sl->outfill_timer.data = (unsigned long)sl;
813 sl->outfill_timer.function = sl_outfill;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814#endif
815 slip_devs[i] = dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 return sl;
817}
818
819/*
820 * Open the high-level part of the SLIP channel.
821 * This function is called by the TTY module when the
822 * SLIP line discipline is called for. Because we are
823 * sure the tty line exists, we only have to link it to
824 * a free SLIP channel...
825 *
826 * Called in process context serialized from other ldisc calls.
827 */
828
829static int slip_open(struct tty_struct *tty)
830{
831 struct slip *sl;
832 int err;
833
Alan Cox9ce6cf22007-11-19 15:03:38 +0000834 if (!capable(CAP_NET_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 return -EPERM;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400836
Alan Coxf34d7a52008-04-30 00:54:13 -0700837 if (tty->ops->write == NULL)
838 return -EOPNOTSUPP;
839
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 /* RTnetlink lock is misused here to serialize concurrent
841 opens of slip channels. There are better ways, but it is
842 the simplest one.
843 */
844 rtnl_lock();
845
846 /* Collect hanged up channels. */
847 sl_sync();
848
Alan Cox9ce6cf22007-11-19 15:03:38 +0000849 sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
851 err = -EEXIST;
852 /* First make sure we're not already connected. */
853 if (sl && sl->magic == SLIP_MAGIC)
854 goto err_exit;
855
856 /* OK. Find a free SLIP channel to use. */
857 err = -ENFILE;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000858 sl = sl_alloc(tty_devnum(tty));
859 if (sl == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 goto err_exit;
861
862 sl->tty = tty;
863 tty->disc_data = sl;
864 sl->line = tty_devnum(tty);
865 sl->pid = current->pid;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400866
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 if (!test_bit(SLF_INUSE, &sl->flags)) {
868 /* Perform the low-level SLIP initialization. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000869 err = sl_alloc_bufs(sl, SL_MTU);
870 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 goto err_free_chan;
872
873 set_bit(SLF_INUSE, &sl->flags);
874
Alan Cox9ce6cf22007-11-19 15:03:38 +0000875 err = register_netdevice(sl->dev);
876 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 goto err_free_bufs;
878 }
879
880#ifdef CONFIG_SLIP_SMART
881 if (sl->keepalive) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000882 sl->keepalive_timer.expires = jiffies + sl->keepalive * HZ;
883 add_timer(&sl->keepalive_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 }
885 if (sl->outfill) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000886 sl->outfill_timer.expires = jiffies + sl->outfill * HZ;
887 add_timer(&sl->outfill_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 }
889#endif
890
891 /* Done. We have linked the TTY line to a channel. */
892 rtnl_unlock();
Alan Cox33f0f882006-01-09 20:54:13 -0800893 tty->receive_room = 65536; /* We don't flow control */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 return sl->dev->base_addr;
895
896err_free_bufs:
897 sl_free_bufs(sl);
898
899err_free_chan:
900 sl->tty = NULL;
901 tty->disc_data = NULL;
902 clear_bit(SLF_INUSE, &sl->flags);
903
904err_exit:
905 rtnl_unlock();
906
907 /* Count references from TTY module */
908 return err;
909}
910
911/*
912
913 FIXME: 1,2 are fixed 3 was never true anyway.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 Let me to blame a bit.
916 1. TTY module calls this funstion on soft interrupt.
917 2. TTY module calls this function WITH MASKED INTERRUPTS!
918 3. TTY module does not notify us about line discipline
919 shutdown,
920
921 Seems, now it is clean. The solution is to consider netdevice and
922 line discipline sides as two independent threads.
923
924 By-product (not desired): sl? does not feel hangups and remains open.
925 It is supposed, that user level program (dip, diald, slattach...)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400926 will catch SIGHUP and make the rest of work.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928 I see no way to make more with current tty code. --ANK
929 */
930
931/*
932 * Close down a SLIP channel.
933 * This means flushing out any pending queues, and then returning. This
934 * call is serialized against other ldisc functions.
935 */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000936static void slip_close(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
Alan Cox9ce6cf22007-11-19 15:03:38 +0000938 struct slip *sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
940 /* First make sure we're connected. */
941 if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty)
942 return;
943
944 tty->disc_data = NULL;
945 sl->tty = NULL;
946 if (!sl->leased)
947 sl->line = 0;
948
949 /* VSV = very important to remove timers */
950#ifdef CONFIG_SLIP_SMART
951 del_timer_sync(&sl->keepalive_timer);
952 del_timer_sync(&sl->outfill_timer);
953#endif
954
955 /* Count references from TTY module */
956}
957
958 /************************************************************************
959 * STANDARD SLIP ENCAPSULATION *
960 ************************************************************************/
961
Alan Cox9ce6cf22007-11-19 15:03:38 +0000962static int slip_esc(unsigned char *s, unsigned char *d, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963{
964 unsigned char *ptr = d;
965 unsigned char c;
966
967 /*
968 * Send an initial END character to flush out any
969 * data that may have accumulated in the receiver
970 * due to line noise.
971 */
972
973 *ptr++ = END;
974
975 /*
976 * For each byte in the packet, send the appropriate
977 * character sequence, according to the SLIP protocol.
978 */
979
980 while (len-- > 0) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000981 switch (c = *s++) {
982 case END:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 *ptr++ = ESC;
984 *ptr++ = ESC_END;
985 break;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000986 case ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 *ptr++ = ESC;
988 *ptr++ = ESC_ESC;
989 break;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000990 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 *ptr++ = c;
992 break;
993 }
994 }
995 *ptr++ = END;
996 return (ptr - d);
997}
998
999static void slip_unesc(struct slip *sl, unsigned char s)
1000{
1001
Alan Cox9ce6cf22007-11-19 15:03:38 +00001002 switch (s) {
1003 case END:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004#ifdef CONFIG_SLIP_SMART
1005 /* drop keeptest bit = VSV */
1006 if (test_bit(SLF_KEEPTEST, &sl->flags))
1007 clear_bit(SLF_KEEPTEST, &sl->flags);
1008#endif
1009
Alan Cox9ce6cf22007-11-19 15:03:38 +00001010 if (!test_and_clear_bit(SLF_ERROR, &sl->flags)
1011 && (sl->rcount > 2))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 sl_bump(sl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 clear_bit(SLF_ESCAPE, &sl->flags);
1014 sl->rcount = 0;
1015 return;
1016
Alan Cox9ce6cf22007-11-19 15:03:38 +00001017 case ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 set_bit(SLF_ESCAPE, &sl->flags);
1019 return;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001020 case ESC_ESC:
1021 if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 s = ESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 break;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001024 case ESC_END:
1025 if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 s = END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 break;
1028 }
1029 if (!test_bit(SLF_ERROR, &sl->flags)) {
1030 if (sl->rcount < sl->buffsize) {
1031 sl->rbuff[sl->rcount++] = s;
1032 return;
1033 }
1034 sl->rx_over_errors++;
1035 set_bit(SLF_ERROR, &sl->flags);
1036 }
1037}
1038
1039
1040#ifdef CONFIG_SLIP_MODE_SLIP6
1041/************************************************************************
1042 * 6 BIT SLIP ENCAPSULATION *
1043 ************************************************************************/
1044
Alan Cox9ce6cf22007-11-19 15:03:38 +00001045static int slip_esc6(unsigned char *s, unsigned char *d, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046{
1047 unsigned char *ptr = d;
1048 unsigned char c;
1049 int i;
1050 unsigned short v = 0;
1051 short bits = 0;
1052
1053 /*
1054 * Send an initial END character to flush out any
1055 * data that may have accumulated in the receiver
1056 * due to line noise.
1057 */
1058
1059 *ptr++ = 0x70;
1060
1061 /*
1062 * Encode the packet into printable ascii characters
1063 */
1064
1065 for (i = 0; i < len; ++i) {
1066 v = (v << 8) | s[i];
1067 bits += 8;
1068 while (bits >= 6) {
1069 bits -= 6;
1070 c = 0x30 + ((v >> bits) & 0x3F);
1071 *ptr++ = c;
1072 }
1073 }
1074 if (bits) {
1075 c = 0x30 + ((v << (6 - bits)) & 0x3F);
1076 *ptr++ = c;
1077 }
1078 *ptr++ = 0x70;
1079 return ptr - d;
1080}
1081
Alan Cox9ce6cf22007-11-19 15:03:38 +00001082static void slip_unesc6(struct slip *sl, unsigned char s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083{
1084 unsigned char c;
1085
1086 if (s == 0x70) {
1087#ifdef CONFIG_SLIP_SMART
1088 /* drop keeptest bit = VSV */
1089 if (test_bit(SLF_KEEPTEST, &sl->flags))
1090 clear_bit(SLF_KEEPTEST, &sl->flags);
1091#endif
1092
Alan Cox9ce6cf22007-11-19 15:03:38 +00001093 if (!test_and_clear_bit(SLF_ERROR, &sl->flags)
1094 && (sl->rcount > 2))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 sl_bump(sl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 sl->rcount = 0;
1097 sl->xbits = 0;
1098 sl->xdata = 0;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001099 } else if (s >= 0x30 && s < 0x70) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 sl->xdata = (sl->xdata << 6) | ((s - 0x30) & 0x3F);
1101 sl->xbits += 6;
1102 if (sl->xbits >= 8) {
1103 sl->xbits -= 8;
1104 c = (unsigned char)(sl->xdata >> sl->xbits);
1105 if (!test_bit(SLF_ERROR, &sl->flags)) {
1106 if (sl->rcount < sl->buffsize) {
1107 sl->rbuff[sl->rcount++] = c;
1108 return;
1109 }
1110 sl->rx_over_errors++;
1111 set_bit(SLF_ERROR, &sl->flags);
1112 }
1113 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115}
1116#endif /* CONFIG_SLIP_MODE_SLIP6 */
1117
1118/* Perform I/O control on an active SLIP channel. */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001119static int slip_ioctl(struct tty_struct *tty, struct file *file,
1120 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
Alan Cox9ce6cf22007-11-19 15:03:38 +00001122 struct slip *sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 unsigned int tmp;
1124 int __user *p = (int __user *)arg;
1125
1126 /* First make sure we're connected. */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001127 if (!sl || sl->magic != SLIP_MAGIC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129
Alan Cox9ce6cf22007-11-19 15:03:38 +00001130 switch (cmd) {
1131 case SIOCGIFNAME:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 tmp = strlen(sl->dev->name) + 1;
1133 if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
1134 return -EFAULT;
1135 return 0;
1136
1137 case SIOCGIFENCAP:
1138 if (put_user(sl->mode, p))
1139 return -EFAULT;
1140 return 0;
1141
1142 case SIOCSIFENCAP:
1143 if (get_user(tmp, p))
1144 return -EFAULT;
1145#ifndef SL_INCLUDE_CSLIP
Alan Cox9ce6cf22007-11-19 15:03:38 +00001146 if (tmp & (SL_MODE_CSLIP|SL_MODE_ADAPTIVE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148#else
1149 if ((tmp & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) ==
Alan Cox9ce6cf22007-11-19 15:03:38 +00001150 (SL_MODE_ADAPTIVE | SL_MODE_CSLIP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 /* return -EINVAL; */
1152 tmp &= ~SL_MODE_ADAPTIVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153#endif
1154#ifndef CONFIG_SLIP_MODE_SLIP6
Alan Cox9ce6cf22007-11-19 15:03:38 +00001155 if (tmp & SL_MODE_SLIP6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157#endif
1158 sl->mode = tmp;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001159 sl->dev->type = ARPHRD_SLIP + sl->mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 return 0;
1161
Alan Cox9ce6cf22007-11-19 15:03:38 +00001162 case SIOCSIFHWADDR:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return -EINVAL;
1164
1165#ifdef CONFIG_SLIP_SMART
1166 /* VSV changes start here */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001167 case SIOCSKEEPALIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 if (get_user(tmp, p))
1169 return -EFAULT;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001170 if (tmp > 255) /* max for unchar */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 return -EINVAL;
1172
1173 spin_lock_bh(&sl->lock);
1174 if (!sl->tty) {
1175 spin_unlock_bh(&sl->lock);
1176 return -ENODEV;
1177 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001178 sl->keepalive = (u8)tmp;
1179 if (sl->keepalive != 0) {
1180 mod_timer(&sl->keepalive_timer,
1181 jiffies + sl->keepalive * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 set_bit(SLF_KEEPTEST, &sl->flags);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001183 } else
1184 del_timer(&sl->keepalive_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 spin_unlock_bh(&sl->lock);
1186 return 0;
1187
Alan Cox9ce6cf22007-11-19 15:03:38 +00001188 case SIOCGKEEPALIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 if (put_user(sl->keepalive, p))
1190 return -EFAULT;
1191 return 0;
1192
Alan Cox9ce6cf22007-11-19 15:03:38 +00001193 case SIOCSOUTFILL:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 if (get_user(tmp, p))
1195 return -EFAULT;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001196 if (tmp > 255) /* max for unchar */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 return -EINVAL;
1198 spin_lock_bh(&sl->lock);
1199 if (!sl->tty) {
1200 spin_unlock_bh(&sl->lock);
1201 return -ENODEV;
1202 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001203 sl->outfill = (u8)tmp;
1204 if (sl->outfill != 0) {
1205 mod_timer(&sl->outfill_timer,
1206 jiffies + sl->outfill * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 set_bit(SLF_OUTWAIT, &sl->flags);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001208 } else
1209 del_timer(&sl->outfill_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 spin_unlock_bh(&sl->lock);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001211 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Alan Cox9ce6cf22007-11-19 15:03:38 +00001213 case SIOCGOUTFILL:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 if (put_user(sl->outfill, p))
1215 return -EFAULT;
1216 return 0;
1217 /* VSV changes end */
1218#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 default:
Alan Coxd0127532007-11-07 01:27:34 -08001220 return tty_mode_ioctl(tty, file, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 }
1222}
1223
1224/* VSV changes start here */
1225#ifdef CONFIG_SLIP_SMART
1226/* function do_ioctl called from net/core/dev.c
1227 to allow get/set outfill/keepalive parameter
1228 by ifconfig */
1229
Alan Cox9ce6cf22007-11-19 15:03:38 +00001230static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231{
1232 struct slip *sl = netdev_priv(dev);
1233 unsigned long *p = (unsigned long *)&rq->ifr_ifru;
1234
1235 if (sl == NULL) /* Allocation failed ?? */
1236 return -ENODEV;
1237
1238 spin_lock_bh(&sl->lock);
1239
1240 if (!sl->tty) {
1241 spin_unlock_bh(&sl->lock);
1242 return -ENODEV;
1243 }
1244
Alan Cox9ce6cf22007-11-19 15:03:38 +00001245 switch (cmd) {
1246 case SIOCSKEEPALIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 /* max for unchar */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001248 if ((unsigned)*p > 255) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 spin_unlock_bh(&sl->lock);
1250 return -EINVAL;
1251 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001252 sl->keepalive = (u8)*p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 if (sl->keepalive != 0) {
Alan Cox9ce6cf22007-11-19 15:03:38 +00001254 sl->keepalive_timer.expires =
1255 jiffies + sl->keepalive * HZ;
1256 mod_timer(&sl->keepalive_timer,
1257 jiffies + sl->keepalive * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 set_bit(SLF_KEEPTEST, &sl->flags);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001259 } else
1260 del_timer(&sl->keepalive_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 break;
1262
Alan Cox9ce6cf22007-11-19 15:03:38 +00001263 case SIOCGKEEPALIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 *p = sl->keepalive;
1265 break;
1266
Alan Cox9ce6cf22007-11-19 15:03:38 +00001267 case SIOCSOUTFILL:
1268 if ((unsigned)*p > 255) { /* max for unchar */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 spin_unlock_bh(&sl->lock);
1270 return -EINVAL;
1271 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001272 sl->outfill = (u8)*p;
1273 if (sl->outfill != 0) {
1274 mod_timer(&sl->outfill_timer,
1275 jiffies + sl->outfill * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 set_bit(SLF_OUTWAIT, &sl->flags);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001277 } else
1278 del_timer(&sl->outfill_timer);
1279 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Alan Cox9ce6cf22007-11-19 15:03:38 +00001281 case SIOCGOUTFILL:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 *p = sl->outfill;
1283 break;
1284
Alan Cox9ce6cf22007-11-19 15:03:38 +00001285 case SIOCSLEASE:
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001286 /* Resolve race condition, when ioctl'ing hanged up
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 and opened by another process device.
1288 */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001289 if (sl->tty != current->signal->tty &&
1290 sl->pid != current->pid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 spin_unlock_bh(&sl->lock);
1292 return -EPERM;
1293 }
1294 sl->leased = 0;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001295 if (*p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 sl->leased = 1;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001297 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Alan Cox9ce6cf22007-11-19 15:03:38 +00001299 case SIOCGLEASE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 *p = sl->leased;
1301 };
1302 spin_unlock_bh(&sl->lock);
1303 return 0;
1304}
1305#endif
1306/* VSV changes end */
1307
Alan Coxa352def2008-07-16 21:53:12 +01001308static struct tty_ldisc_ops sl_ldisc = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 .owner = THIS_MODULE,
1310 .magic = TTY_LDISC_MAGIC,
1311 .name = "slip",
1312 .open = slip_open,
1313 .close = slip_close,
1314 .ioctl = slip_ioctl,
1315 .receive_buf = slip_receive_buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 .write_wakeup = slip_write_wakeup,
1317};
1318
1319static int __init slip_init(void)
1320{
1321 int status;
1322
1323 if (slip_maxdev < 4)
1324 slip_maxdev = 4; /* Sanity */
1325
1326 printk(KERN_INFO "SLIP: version %s (dynamic channels, max=%d)"
1327#ifdef CONFIG_SLIP_MODE_SLIP6
1328 " (6 bit encapsulation enabled)"
1329#endif
1330 ".\n",
Alan Cox9ce6cf22007-11-19 15:03:38 +00001331 SLIP_VERSION, slip_maxdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332#if defined(SL_INCLUDE_CSLIP)
1333 printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n");
1334#endif
1335#ifdef CONFIG_SLIP_SMART
1336 printk(KERN_INFO "SLIP linefill/keepalive option.\n");
1337#endif
1338
Alan Cox9ce6cf22007-11-19 15:03:38 +00001339 slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev,
1340 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 if (!slip_devs) {
Alan Cox9ce6cf22007-11-19 15:03:38 +00001342 printk(KERN_ERR "SLIP: Can't allocate slip devices array.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 return -ENOMEM;
1344 }
1345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 /* Fill in our line protocol discipline, and register it */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001347 status = tty_register_ldisc(N_SLIP, &sl_ldisc);
1348 if (status != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
1350 kfree(slip_devs);
1351 }
1352 return status;
1353}
1354
1355static void __exit slip_exit(void)
1356{
1357 int i;
1358 struct net_device *dev;
1359 struct slip *sl;
1360 unsigned long timeout = jiffies + HZ;
1361 int busy = 0;
1362
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001363 if (slip_devs == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 return;
1365
1366 /* First of all: check for active disciplines and hangup them.
1367 */
1368 do {
Nishanth Aravamudana9fc2512005-05-01 23:34:57 -07001369 if (busy)
1370 msleep_interruptible(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
1372 busy = 0;
1373 for (i = 0; i < slip_maxdev; i++) {
1374 dev = slip_devs[i];
1375 if (!dev)
1376 continue;
1377 sl = netdev_priv(dev);
1378 spin_lock_bh(&sl->lock);
1379 if (sl->tty) {
1380 busy++;
1381 tty_hangup(sl->tty);
1382 }
1383 spin_unlock_bh(&sl->lock);
1384 }
1385 } while (busy && time_before(jiffies, timeout));
1386
1387
1388 for (i = 0; i < slip_maxdev; i++) {
1389 dev = slip_devs[i];
1390 if (!dev)
1391 continue;
1392 slip_devs[i] = NULL;
1393
1394 sl = netdev_priv(dev);
1395 if (sl->tty) {
1396 printk(KERN_ERR "%s: tty discipline still running\n",
1397 dev->name);
1398 /* Intentionally leak the control block. */
1399 dev->destructor = NULL;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
1402 unregister_netdev(dev);
1403 }
1404
1405 kfree(slip_devs);
1406 slip_devs = NULL;
1407
Alan Cox9ce6cf22007-11-19 15:03:38 +00001408 i = tty_unregister_ldisc(N_SLIP);
1409 if (i != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411}
1412
1413module_init(slip_init);
1414module_exit(slip_exit);
1415
1416#ifdef CONFIG_SLIP_SMART
1417/*
1418 * This is start of the code for multislip style line checking
1419 * added by Stanislav Voronyi. All changes before marked VSV
1420 */
1421
1422static void sl_outfill(unsigned long sls)
1423{
Alan Cox9ce6cf22007-11-19 15:03:38 +00001424 struct slip *sl = (struct slip *)sls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
1426 spin_lock(&sl->lock);
1427
1428 if (sl->tty == NULL)
1429 goto out;
1430
Alan Cox9ce6cf22007-11-19 15:03:38 +00001431 if (sl->outfill) {
1432 if (test_bit(SLF_OUTWAIT, &sl->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 /* no packets were transmitted, do outfill */
1434#ifdef CONFIG_SLIP_MODE_SLIP6
1435 unsigned char s = (sl->mode & SL_MODE_SLIP6)?0x70:END;
1436#else
1437 unsigned char s = END;
1438#endif
1439 /* put END into tty queue. Is it right ??? */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001440 if (!netif_queue_stopped(sl->dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 /* if device busy no outfill */
Alan Coxf34d7a52008-04-30 00:54:13 -07001442 sl->tty->ops->write(sl->tty, &s, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001444 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 set_bit(SLF_OUTWAIT, &sl->flags);
1446
1447 mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
1448 }
1449out:
1450 spin_unlock(&sl->lock);
1451}
1452
1453static void sl_keepalive(unsigned long sls)
1454{
Alan Cox9ce6cf22007-11-19 15:03:38 +00001455 struct slip *sl = (struct slip *)sls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457 spin_lock(&sl->lock);
1458
1459 if (sl->tty == NULL)
1460 goto out;
1461
Alan Cox9ce6cf22007-11-19 15:03:38 +00001462 if (sl->keepalive) {
1463 if (test_bit(SLF_KEEPTEST, &sl->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 /* keepalive still high :(, we must hangup */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001465 if (sl->outfill)
1466 /* outfill timer must be deleted too */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 (void)del_timer(&sl->outfill_timer);
1468 printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001469 /* this must hangup tty & close slip */
1470 tty_hangup(sl->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 /* I think we need not something else */
1472 goto out;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001473 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 set_bit(SLF_KEEPTEST, &sl->flags);
1475
1476 mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
1477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478out:
1479 spin_unlock(&sl->lock);
1480}
1481
1482#endif
1483MODULE_LICENSE("GPL");
1484MODULE_ALIAS_LDISC(N_SLIP);