blob: 8e1c0baf6958287365d5b2f1e634cedc33e46bb3 [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);
487 return 0;
488 }
489 if (sl->tty == NULL) {
490 spin_unlock(&sl->lock);
491 dev_kfree_skb(skb);
492 return 0;
493 }
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);
501 return 0;
502}
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
606 dev->tx_timeout = sl_tx_timeout;
607 dev->watchdog_timeo = 20*HZ;
608#endif
609 return 0;
610}
611
612
613static void sl_uninit(struct net_device *dev)
614{
615 struct slip *sl = netdev_priv(dev);
616
617 sl_free_bufs(sl);
618}
619
620static void sl_setup(struct net_device *dev)
621{
622 dev->init = sl_init;
623 dev->uninit = sl_uninit;
624 dev->open = sl_open;
625 dev->destructor = free_netdev;
626 dev->stop = sl_close;
627 dev->get_stats = sl_get_stats;
628 dev->change_mtu = sl_change_mtu;
629 dev->hard_start_xmit = sl_xmit;
630#ifdef CONFIG_SLIP_SMART
631 dev->do_ioctl = sl_ioctl;
632#endif
633 dev->hard_header_len = 0;
634 dev->addr_len = 0;
635 dev->tx_queue_len = 10;
636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 /* New-style flags. */
638 dev->flags = IFF_NOARP|IFF_POINTOPOINT|IFF_MULTICAST;
639}
640
641/******************************************
642 Routines looking at TTY side.
643 ******************************************/
644
645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646/*
647 * Handle the 'receiver data ready' interrupt.
648 * This function is called by the 'tty_io' module in the kernel when
649 * a block of SLIP data has been received, which can now be decapsulated
650 * and sent on to some IP layer for further processing. This will not
651 * be re-entered while running but other ldisc functions may be called
652 * in parallel
653 */
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400654
Alan Cox9ce6cf22007-11-19 15:03:38 +0000655static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp,
656 char *fp, int count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
Alan Cox9ce6cf22007-11-19 15:03:38 +0000658 struct slip *sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Alan Cox9ce6cf22007-11-19 15:03:38 +0000660 if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 return;
662
663 /* Read the characters out of the buffer */
664 while (count--) {
665 if (fp && *fp++) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000666 if (!test_and_set_bit(SLF_ERROR, &sl->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 sl->rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 cp++;
669 continue;
670 }
671#ifdef CONFIG_SLIP_MODE_SLIP6
672 if (sl->mode & SL_MODE_SLIP6)
673 slip_unesc6(sl, *cp++);
674 else
675#endif
676 slip_unesc(sl, *cp++);
677 }
678}
679
680/************************************
681 * slip_open helper routines.
682 ************************************/
683
684/* Collect hanged up channels */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685static void sl_sync(void)
686{
687 int i;
688 struct net_device *dev;
689 struct slip *sl;
690
691 for (i = 0; i < slip_maxdev; i++) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000692 dev = slip_devs[i];
693 if (dev == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 break;
695
696 sl = netdev_priv(dev);
697 if (sl->tty || sl->leased)
698 continue;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000699 if (dev->flags & IFF_UP)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 dev_close(dev);
701 }
702}
703
704
705/* Find a free SLIP channel, and link in this `tty' line. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000706static struct slip *sl_alloc(dev_t line)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
708 int i;
709 int sel = -1;
710 int score = -1;
711 struct net_device *dev = NULL;
712 struct slip *sl;
713
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400714 if (slip_devs == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 return NULL; /* Master array missing ! */
716
717 for (i = 0; i < slip_maxdev; i++) {
718 dev = slip_devs[i];
719 if (dev == NULL)
720 break;
721
722 sl = netdev_priv(dev);
723 if (sl->leased) {
724 if (sl->line != line)
725 continue;
726 if (sl->tty)
727 return NULL;
728
729 /* Clear ESCAPE & ERROR flags */
730 sl->flags &= (1 << SLF_INUSE);
731 return sl;
732 }
733
734 if (sl->tty)
735 continue;
736
737 if (current->pid == sl->pid) {
738 if (sl->line == line && score < 3) {
739 sel = i;
740 score = 3;
741 continue;
742 }
743 if (score < 2) {
744 sel = i;
745 score = 2;
746 }
747 continue;
748 }
749 if (sl->line == line && score < 1) {
750 sel = i;
751 score = 1;
752 continue;
753 }
754 if (score < 0) {
755 sel = i;
756 score = 0;
757 }
758 }
759
760 if (sel >= 0) {
761 i = sel;
762 dev = slip_devs[i];
763 if (score > 1) {
764 sl = netdev_priv(dev);
765 sl->flags &= (1 << SLF_INUSE);
766 return sl;
767 }
768 }
769
770 /* Sorry, too many, all slots in use */
771 if (i >= slip_maxdev)
772 return NULL;
773
774 if (dev) {
775 sl = netdev_priv(dev);
776 if (test_bit(SLF_INUSE, &sl->flags)) {
777 unregister_netdevice(dev);
778 dev = NULL;
779 slip_devs[i] = NULL;
780 }
781 }
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400782
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 if (!dev) {
784 char name[IFNAMSIZ];
785 sprintf(name, "sl%d", i);
786
787 dev = alloc_netdev(sizeof(*sl), name, sl_setup);
788 if (!dev)
789 return NULL;
790 dev->base_addr = i;
791 }
792
793 sl = netdev_priv(dev);
794
795 /* Initialize channel control data */
796 sl->magic = SLIP_MAGIC;
797 sl->dev = dev;
798 spin_lock_init(&sl->lock);
799 sl->mode = SL_MODE_DEFAULT;
800#ifdef CONFIG_SLIP_SMART
Alan Cox9ce6cf22007-11-19 15:03:38 +0000801 /* initialize timer_list struct */
802 init_timer(&sl->keepalive_timer);
803 sl->keepalive_timer.data = (unsigned long)sl;
804 sl->keepalive_timer.function = sl_keepalive;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 init_timer(&sl->outfill_timer);
Alan Cox9ce6cf22007-11-19 15:03:38 +0000806 sl->outfill_timer.data = (unsigned long)sl;
807 sl->outfill_timer.function = sl_outfill;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808#endif
809 slip_devs[i] = dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 return sl;
811}
812
813/*
814 * Open the high-level part of the SLIP channel.
815 * This function is called by the TTY module when the
816 * SLIP line discipline is called for. Because we are
817 * sure the tty line exists, we only have to link it to
818 * a free SLIP channel...
819 *
820 * Called in process context serialized from other ldisc calls.
821 */
822
823static int slip_open(struct tty_struct *tty)
824{
825 struct slip *sl;
826 int err;
827
Alan Cox9ce6cf22007-11-19 15:03:38 +0000828 if (!capable(CAP_NET_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 return -EPERM;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400830
Alan Coxf34d7a52008-04-30 00:54:13 -0700831 if (tty->ops->write == NULL)
832 return -EOPNOTSUPP;
833
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 /* RTnetlink lock is misused here to serialize concurrent
835 opens of slip channels. There are better ways, but it is
836 the simplest one.
837 */
838 rtnl_lock();
839
840 /* Collect hanged up channels. */
841 sl_sync();
842
Alan Cox9ce6cf22007-11-19 15:03:38 +0000843 sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
845 err = -EEXIST;
846 /* First make sure we're not already connected. */
847 if (sl && sl->magic == SLIP_MAGIC)
848 goto err_exit;
849
850 /* OK. Find a free SLIP channel to use. */
851 err = -ENFILE;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000852 sl = sl_alloc(tty_devnum(tty));
853 if (sl == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 goto err_exit;
855
856 sl->tty = tty;
857 tty->disc_data = sl;
858 sl->line = tty_devnum(tty);
859 sl->pid = current->pid;
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 if (!test_bit(SLF_INUSE, &sl->flags)) {
862 /* Perform the low-level SLIP initialization. */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000863 err = sl_alloc_bufs(sl, SL_MTU);
864 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 goto err_free_chan;
866
867 set_bit(SLF_INUSE, &sl->flags);
868
Alan Cox9ce6cf22007-11-19 15:03:38 +0000869 err = register_netdevice(sl->dev);
870 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 goto err_free_bufs;
872 }
873
874#ifdef CONFIG_SLIP_SMART
875 if (sl->keepalive) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000876 sl->keepalive_timer.expires = jiffies + sl->keepalive * HZ;
877 add_timer(&sl->keepalive_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 }
879 if (sl->outfill) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000880 sl->outfill_timer.expires = jiffies + sl->outfill * HZ;
881 add_timer(&sl->outfill_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 }
883#endif
884
885 /* Done. We have linked the TTY line to a channel. */
886 rtnl_unlock();
Alan Cox33f0f882006-01-09 20:54:13 -0800887 tty->receive_room = 65536; /* We don't flow control */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 return sl->dev->base_addr;
889
890err_free_bufs:
891 sl_free_bufs(sl);
892
893err_free_chan:
894 sl->tty = NULL;
895 tty->disc_data = NULL;
896 clear_bit(SLF_INUSE, &sl->flags);
897
898err_exit:
899 rtnl_unlock();
900
901 /* Count references from TTY module */
902 return err;
903}
904
905/*
906
907 FIXME: 1,2 are fixed 3 was never true anyway.
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400908
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 Let me to blame a bit.
910 1. TTY module calls this funstion on soft interrupt.
911 2. TTY module calls this function WITH MASKED INTERRUPTS!
912 3. TTY module does not notify us about line discipline
913 shutdown,
914
915 Seems, now it is clean. The solution is to consider netdevice and
916 line discipline sides as two independent threads.
917
918 By-product (not desired): sl? does not feel hangups and remains open.
919 It is supposed, that user level program (dip, diald, slattach...)
Jeff Garzik6aa20a22006-09-13 13:24:59 -0400920 will catch SIGHUP and make the rest of work.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
922 I see no way to make more with current tty code. --ANK
923 */
924
925/*
926 * Close down a SLIP channel.
927 * This means flushing out any pending queues, and then returning. This
928 * call is serialized against other ldisc functions.
929 */
Alan Cox9ce6cf22007-11-19 15:03:38 +0000930static void slip_close(struct tty_struct *tty)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931{
Alan Cox9ce6cf22007-11-19 15:03:38 +0000932 struct slip *sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
934 /* First make sure we're connected. */
935 if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty)
936 return;
937
938 tty->disc_data = NULL;
939 sl->tty = NULL;
940 if (!sl->leased)
941 sl->line = 0;
942
943 /* VSV = very important to remove timers */
944#ifdef CONFIG_SLIP_SMART
945 del_timer_sync(&sl->keepalive_timer);
946 del_timer_sync(&sl->outfill_timer);
947#endif
948
949 /* Count references from TTY module */
950}
951
952 /************************************************************************
953 * STANDARD SLIP ENCAPSULATION *
954 ************************************************************************/
955
Alan Cox9ce6cf22007-11-19 15:03:38 +0000956static int slip_esc(unsigned char *s, unsigned char *d, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957{
958 unsigned char *ptr = d;
959 unsigned char c;
960
961 /*
962 * Send an initial END character to flush out any
963 * data that may have accumulated in the receiver
964 * due to line noise.
965 */
966
967 *ptr++ = END;
968
969 /*
970 * For each byte in the packet, send the appropriate
971 * character sequence, according to the SLIP protocol.
972 */
973
974 while (len-- > 0) {
Alan Cox9ce6cf22007-11-19 15:03:38 +0000975 switch (c = *s++) {
976 case END:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 *ptr++ = ESC;
978 *ptr++ = ESC_END;
979 break;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000980 case ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 *ptr++ = ESC;
982 *ptr++ = ESC_ESC;
983 break;
Alan Cox9ce6cf22007-11-19 15:03:38 +0000984 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 *ptr++ = c;
986 break;
987 }
988 }
989 *ptr++ = END;
990 return (ptr - d);
991}
992
993static void slip_unesc(struct slip *sl, unsigned char s)
994{
995
Alan Cox9ce6cf22007-11-19 15:03:38 +0000996 switch (s) {
997 case END:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998#ifdef CONFIG_SLIP_SMART
999 /* drop keeptest bit = VSV */
1000 if (test_bit(SLF_KEEPTEST, &sl->flags))
1001 clear_bit(SLF_KEEPTEST, &sl->flags);
1002#endif
1003
Alan Cox9ce6cf22007-11-19 15:03:38 +00001004 if (!test_and_clear_bit(SLF_ERROR, &sl->flags)
1005 && (sl->rcount > 2))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 sl_bump(sl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 clear_bit(SLF_ESCAPE, &sl->flags);
1008 sl->rcount = 0;
1009 return;
1010
Alan Cox9ce6cf22007-11-19 15:03:38 +00001011 case ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 set_bit(SLF_ESCAPE, &sl->flags);
1013 return;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001014 case ESC_ESC:
1015 if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 s = ESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 break;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001018 case ESC_END:
1019 if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 s = END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 break;
1022 }
1023 if (!test_bit(SLF_ERROR, &sl->flags)) {
1024 if (sl->rcount < sl->buffsize) {
1025 sl->rbuff[sl->rcount++] = s;
1026 return;
1027 }
1028 sl->rx_over_errors++;
1029 set_bit(SLF_ERROR, &sl->flags);
1030 }
1031}
1032
1033
1034#ifdef CONFIG_SLIP_MODE_SLIP6
1035/************************************************************************
1036 * 6 BIT SLIP ENCAPSULATION *
1037 ************************************************************************/
1038
Alan Cox9ce6cf22007-11-19 15:03:38 +00001039static int slip_esc6(unsigned char *s, unsigned char *d, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040{
1041 unsigned char *ptr = d;
1042 unsigned char c;
1043 int i;
1044 unsigned short v = 0;
1045 short bits = 0;
1046
1047 /*
1048 * Send an initial END character to flush out any
1049 * data that may have accumulated in the receiver
1050 * due to line noise.
1051 */
1052
1053 *ptr++ = 0x70;
1054
1055 /*
1056 * Encode the packet into printable ascii characters
1057 */
1058
1059 for (i = 0; i < len; ++i) {
1060 v = (v << 8) | s[i];
1061 bits += 8;
1062 while (bits >= 6) {
1063 bits -= 6;
1064 c = 0x30 + ((v >> bits) & 0x3F);
1065 *ptr++ = c;
1066 }
1067 }
1068 if (bits) {
1069 c = 0x30 + ((v << (6 - bits)) & 0x3F);
1070 *ptr++ = c;
1071 }
1072 *ptr++ = 0x70;
1073 return ptr - d;
1074}
1075
Alan Cox9ce6cf22007-11-19 15:03:38 +00001076static void slip_unesc6(struct slip *sl, unsigned char s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077{
1078 unsigned char c;
1079
1080 if (s == 0x70) {
1081#ifdef CONFIG_SLIP_SMART
1082 /* drop keeptest bit = VSV */
1083 if (test_bit(SLF_KEEPTEST, &sl->flags))
1084 clear_bit(SLF_KEEPTEST, &sl->flags);
1085#endif
1086
Alan Cox9ce6cf22007-11-19 15:03:38 +00001087 if (!test_and_clear_bit(SLF_ERROR, &sl->flags)
1088 && (sl->rcount > 2))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 sl_bump(sl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 sl->rcount = 0;
1091 sl->xbits = 0;
1092 sl->xdata = 0;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001093 } else if (s >= 0x30 && s < 0x70) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 sl->xdata = (sl->xdata << 6) | ((s - 0x30) & 0x3F);
1095 sl->xbits += 6;
1096 if (sl->xbits >= 8) {
1097 sl->xbits -= 8;
1098 c = (unsigned char)(sl->xdata >> sl->xbits);
1099 if (!test_bit(SLF_ERROR, &sl->flags)) {
1100 if (sl->rcount < sl->buffsize) {
1101 sl->rbuff[sl->rcount++] = c;
1102 return;
1103 }
1104 sl->rx_over_errors++;
1105 set_bit(SLF_ERROR, &sl->flags);
1106 }
1107 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109}
1110#endif /* CONFIG_SLIP_MODE_SLIP6 */
1111
1112/* Perform I/O control on an active SLIP channel. */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001113static int slip_ioctl(struct tty_struct *tty, struct file *file,
1114 unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115{
Alan Cox9ce6cf22007-11-19 15:03:38 +00001116 struct slip *sl = tty->disc_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 unsigned int tmp;
1118 int __user *p = (int __user *)arg;
1119
1120 /* First make sure we're connected. */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001121 if (!sl || sl->magic != SLIP_MAGIC)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123
Alan Cox9ce6cf22007-11-19 15:03:38 +00001124 switch (cmd) {
1125 case SIOCGIFNAME:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 tmp = strlen(sl->dev->name) + 1;
1127 if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
1128 return -EFAULT;
1129 return 0;
1130
1131 case SIOCGIFENCAP:
1132 if (put_user(sl->mode, p))
1133 return -EFAULT;
1134 return 0;
1135
1136 case SIOCSIFENCAP:
1137 if (get_user(tmp, p))
1138 return -EFAULT;
1139#ifndef SL_INCLUDE_CSLIP
Alan Cox9ce6cf22007-11-19 15:03:38 +00001140 if (tmp & (SL_MODE_CSLIP|SL_MODE_ADAPTIVE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142#else
1143 if ((tmp & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) ==
Alan Cox9ce6cf22007-11-19 15:03:38 +00001144 (SL_MODE_ADAPTIVE | SL_MODE_CSLIP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 /* return -EINVAL; */
1146 tmp &= ~SL_MODE_ADAPTIVE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147#endif
1148#ifndef CONFIG_SLIP_MODE_SLIP6
Alan Cox9ce6cf22007-11-19 15:03:38 +00001149 if (tmp & SL_MODE_SLIP6)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151#endif
1152 sl->mode = tmp;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001153 sl->dev->type = ARPHRD_SLIP + sl->mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 return 0;
1155
Alan Cox9ce6cf22007-11-19 15:03:38 +00001156 case SIOCSIFHWADDR:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 return -EINVAL;
1158
1159#ifdef CONFIG_SLIP_SMART
1160 /* VSV changes start here */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001161 case SIOCSKEEPALIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 if (get_user(tmp, p))
1163 return -EFAULT;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001164 if (tmp > 255) /* max for unchar */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 return -EINVAL;
1166
1167 spin_lock_bh(&sl->lock);
1168 if (!sl->tty) {
1169 spin_unlock_bh(&sl->lock);
1170 return -ENODEV;
1171 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001172 sl->keepalive = (u8)tmp;
1173 if (sl->keepalive != 0) {
1174 mod_timer(&sl->keepalive_timer,
1175 jiffies + sl->keepalive * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 set_bit(SLF_KEEPTEST, &sl->flags);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001177 } else
1178 del_timer(&sl->keepalive_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 spin_unlock_bh(&sl->lock);
1180 return 0;
1181
Alan Cox9ce6cf22007-11-19 15:03:38 +00001182 case SIOCGKEEPALIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 if (put_user(sl->keepalive, p))
1184 return -EFAULT;
1185 return 0;
1186
Alan Cox9ce6cf22007-11-19 15:03:38 +00001187 case SIOCSOUTFILL:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 if (get_user(tmp, p))
1189 return -EFAULT;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001190 if (tmp > 255) /* max for unchar */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 return -EINVAL;
1192 spin_lock_bh(&sl->lock);
1193 if (!sl->tty) {
1194 spin_unlock_bh(&sl->lock);
1195 return -ENODEV;
1196 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001197 sl->outfill = (u8)tmp;
1198 if (sl->outfill != 0) {
1199 mod_timer(&sl->outfill_timer,
1200 jiffies + sl->outfill * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 set_bit(SLF_OUTWAIT, &sl->flags);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001202 } else
1203 del_timer(&sl->outfill_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 spin_unlock_bh(&sl->lock);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001205 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Alan Cox9ce6cf22007-11-19 15:03:38 +00001207 case SIOCGOUTFILL:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 if (put_user(sl->outfill, p))
1209 return -EFAULT;
1210 return 0;
1211 /* VSV changes end */
1212#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 default:
Alan Coxd0127532007-11-07 01:27:34 -08001214 return tty_mode_ioctl(tty, file, cmd, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 }
1216}
1217
1218/* VSV changes start here */
1219#ifdef CONFIG_SLIP_SMART
1220/* function do_ioctl called from net/core/dev.c
1221 to allow get/set outfill/keepalive parameter
1222 by ifconfig */
1223
Alan Cox9ce6cf22007-11-19 15:03:38 +00001224static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225{
1226 struct slip *sl = netdev_priv(dev);
1227 unsigned long *p = (unsigned long *)&rq->ifr_ifru;
1228
1229 if (sl == NULL) /* Allocation failed ?? */
1230 return -ENODEV;
1231
1232 spin_lock_bh(&sl->lock);
1233
1234 if (!sl->tty) {
1235 spin_unlock_bh(&sl->lock);
1236 return -ENODEV;
1237 }
1238
Alan Cox9ce6cf22007-11-19 15:03:38 +00001239 switch (cmd) {
1240 case SIOCSKEEPALIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 /* max for unchar */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001242 if ((unsigned)*p > 255) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 spin_unlock_bh(&sl->lock);
1244 return -EINVAL;
1245 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001246 sl->keepalive = (u8)*p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 if (sl->keepalive != 0) {
Alan Cox9ce6cf22007-11-19 15:03:38 +00001248 sl->keepalive_timer.expires =
1249 jiffies + sl->keepalive * HZ;
1250 mod_timer(&sl->keepalive_timer,
1251 jiffies + sl->keepalive * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 set_bit(SLF_KEEPTEST, &sl->flags);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001253 } else
1254 del_timer(&sl->keepalive_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 break;
1256
Alan Cox9ce6cf22007-11-19 15:03:38 +00001257 case SIOCGKEEPALIVE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 *p = sl->keepalive;
1259 break;
1260
Alan Cox9ce6cf22007-11-19 15:03:38 +00001261 case SIOCSOUTFILL:
1262 if ((unsigned)*p > 255) { /* max for unchar */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 spin_unlock_bh(&sl->lock);
1264 return -EINVAL;
1265 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001266 sl->outfill = (u8)*p;
1267 if (sl->outfill != 0) {
1268 mod_timer(&sl->outfill_timer,
1269 jiffies + sl->outfill * HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 set_bit(SLF_OUTWAIT, &sl->flags);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001271 } else
1272 del_timer(&sl->outfill_timer);
1273 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Alan Cox9ce6cf22007-11-19 15:03:38 +00001275 case SIOCGOUTFILL:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 *p = sl->outfill;
1277 break;
1278
Alan Cox9ce6cf22007-11-19 15:03:38 +00001279 case SIOCSLEASE:
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001280 /* Resolve race condition, when ioctl'ing hanged up
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 and opened by another process device.
1282 */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001283 if (sl->tty != current->signal->tty &&
1284 sl->pid != current->pid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 spin_unlock_bh(&sl->lock);
1286 return -EPERM;
1287 }
1288 sl->leased = 0;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001289 if (*p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 sl->leased = 1;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001291 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292
Alan Cox9ce6cf22007-11-19 15:03:38 +00001293 case SIOCGLEASE:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 *p = sl->leased;
1295 };
1296 spin_unlock_bh(&sl->lock);
1297 return 0;
1298}
1299#endif
1300/* VSV changes end */
1301
Alan Coxa352def2008-07-16 21:53:12 +01001302static struct tty_ldisc_ops sl_ldisc = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 .owner = THIS_MODULE,
1304 .magic = TTY_LDISC_MAGIC,
1305 .name = "slip",
1306 .open = slip_open,
1307 .close = slip_close,
1308 .ioctl = slip_ioctl,
1309 .receive_buf = slip_receive_buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 .write_wakeup = slip_write_wakeup,
1311};
1312
1313static int __init slip_init(void)
1314{
1315 int status;
1316
1317 if (slip_maxdev < 4)
1318 slip_maxdev = 4; /* Sanity */
1319
1320 printk(KERN_INFO "SLIP: version %s (dynamic channels, max=%d)"
1321#ifdef CONFIG_SLIP_MODE_SLIP6
1322 " (6 bit encapsulation enabled)"
1323#endif
1324 ".\n",
Alan Cox9ce6cf22007-11-19 15:03:38 +00001325 SLIP_VERSION, slip_maxdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326#if defined(SL_INCLUDE_CSLIP)
1327 printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n");
1328#endif
1329#ifdef CONFIG_SLIP_SMART
1330 printk(KERN_INFO "SLIP linefill/keepalive option.\n");
1331#endif
1332
Alan Cox9ce6cf22007-11-19 15:03:38 +00001333 slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev,
1334 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 if (!slip_devs) {
Alan Cox9ce6cf22007-11-19 15:03:38 +00001336 printk(KERN_ERR "SLIP: Can't allocate slip devices array.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 return -ENOMEM;
1338 }
1339
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 /* Fill in our line protocol discipline, and register it */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001341 status = tty_register_ldisc(N_SLIP, &sl_ldisc);
1342 if (status != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
1344 kfree(slip_devs);
1345 }
1346 return status;
1347}
1348
1349static void __exit slip_exit(void)
1350{
1351 int i;
1352 struct net_device *dev;
1353 struct slip *sl;
1354 unsigned long timeout = jiffies + HZ;
1355 int busy = 0;
1356
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001357 if (slip_devs == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 return;
1359
1360 /* First of all: check for active disciplines and hangup them.
1361 */
1362 do {
Nishanth Aravamudana9fc2512005-05-01 23:34:57 -07001363 if (busy)
1364 msleep_interruptible(100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
1366 busy = 0;
1367 for (i = 0; i < slip_maxdev; i++) {
1368 dev = slip_devs[i];
1369 if (!dev)
1370 continue;
1371 sl = netdev_priv(dev);
1372 spin_lock_bh(&sl->lock);
1373 if (sl->tty) {
1374 busy++;
1375 tty_hangup(sl->tty);
1376 }
1377 spin_unlock_bh(&sl->lock);
1378 }
1379 } while (busy && time_before(jiffies, timeout));
1380
1381
1382 for (i = 0; i < slip_maxdev; i++) {
1383 dev = slip_devs[i];
1384 if (!dev)
1385 continue;
1386 slip_devs[i] = NULL;
1387
1388 sl = netdev_priv(dev);
1389 if (sl->tty) {
1390 printk(KERN_ERR "%s: tty discipline still running\n",
1391 dev->name);
1392 /* Intentionally leak the control block. */
1393 dev->destructor = NULL;
Jeff Garzik6aa20a22006-09-13 13:24:59 -04001394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
1396 unregister_netdev(dev);
1397 }
1398
1399 kfree(slip_devs);
1400 slip_devs = NULL;
1401
Alan Cox9ce6cf22007-11-19 15:03:38 +00001402 i = tty_unregister_ldisc(N_SLIP);
1403 if (i != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405}
1406
1407module_init(slip_init);
1408module_exit(slip_exit);
1409
1410#ifdef CONFIG_SLIP_SMART
1411/*
1412 * This is start of the code for multislip style line checking
1413 * added by Stanislav Voronyi. All changes before marked VSV
1414 */
1415
1416static void sl_outfill(unsigned long sls)
1417{
Alan Cox9ce6cf22007-11-19 15:03:38 +00001418 struct slip *sl = (struct slip *)sls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
1420 spin_lock(&sl->lock);
1421
1422 if (sl->tty == NULL)
1423 goto out;
1424
Alan Cox9ce6cf22007-11-19 15:03:38 +00001425 if (sl->outfill) {
1426 if (test_bit(SLF_OUTWAIT, &sl->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 /* no packets were transmitted, do outfill */
1428#ifdef CONFIG_SLIP_MODE_SLIP6
1429 unsigned char s = (sl->mode & SL_MODE_SLIP6)?0x70:END;
1430#else
1431 unsigned char s = END;
1432#endif
1433 /* put END into tty queue. Is it right ??? */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001434 if (!netif_queue_stopped(sl->dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 /* if device busy no outfill */
Alan Coxf34d7a52008-04-30 00:54:13 -07001436 sl->tty->ops->write(sl->tty, &s, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 }
Alan Cox9ce6cf22007-11-19 15:03:38 +00001438 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 set_bit(SLF_OUTWAIT, &sl->flags);
1440
1441 mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
1442 }
1443out:
1444 spin_unlock(&sl->lock);
1445}
1446
1447static void sl_keepalive(unsigned long sls)
1448{
Alan Cox9ce6cf22007-11-19 15:03:38 +00001449 struct slip *sl = (struct slip *)sls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451 spin_lock(&sl->lock);
1452
1453 if (sl->tty == NULL)
1454 goto out;
1455
Alan Cox9ce6cf22007-11-19 15:03:38 +00001456 if (sl->keepalive) {
1457 if (test_bit(SLF_KEEPTEST, &sl->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 /* keepalive still high :(, we must hangup */
Alan Cox9ce6cf22007-11-19 15:03:38 +00001459 if (sl->outfill)
1460 /* outfill timer must be deleted too */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 (void)del_timer(&sl->outfill_timer);
1462 printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
Alan Cox9ce6cf22007-11-19 15:03:38 +00001463 /* this must hangup tty & close slip */
1464 tty_hangup(sl->tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 /* I think we need not something else */
1466 goto out;
Alan Cox9ce6cf22007-11-19 15:03:38 +00001467 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 set_bit(SLF_KEEPTEST, &sl->flags);
1469
1470 mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
1471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472out:
1473 spin_unlock(&sl->lock);
1474}
1475
1476#endif
1477MODULE_LICENSE("GPL");
1478MODULE_ALIAS_LDISC(N_SLIP);