~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/net/ppp_async.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * PPP async serial channel driver for Linux.
  3  *
  4  * Copyright 1999 Paul Mackerras.
  5  *
  6  *  This program is free software; you can redistribute it and/or
  7  *  modify it under the terms of the GNU General Public License
  8  *  as published by the Free Software Foundation; either version
  9  *  2 of the License, or (at your option) any later version.
 10  *
 11  * This driver provides the encapsulation and framing for sending
 12  * and receiving PPP frames over async serial lines.  It relies on
 13  * the generic PPP layer to give it frames to send and to process
 14  * received frames.  It implements the PPP line discipline.
 15  *
 16  * Part of the code in this driver was inspired by the old async-only
 17  * PPP driver, written by Michael Callahan and Al Longyear, and
 18  * subsequently hacked by Paul Mackerras.
 19  *
 20  * ==FILEVERSION 20000227==
 21  */
 22 
 23 #include <linux/module.h>
 24 #include <linux/kernel.h>
 25 #include <linux/skbuff.h>
 26 #include <linux/tty.h>
 27 #include <linux/netdevice.h>
 28 #include <linux/poll.h>
 29 #include <linux/ppp_defs.h>
 30 #include <linux/if_ppp.h>
 31 #include <linux/ppp_channel.h>
 32 #include <linux/spinlock.h>
 33 #include <linux/init.h>
 34 #include <asm/uaccess.h>
 35 
 36 #ifndef spin_trylock_bh
 37 #define spin_trylock_bh(lock)   ({ int __r; local_bh_disable(); \
 38                                    __r = spin_trylock(lock);    \
 39                                    if (!__r) local_bh_enable(); \
 40                                    __r; })
 41 #endif
 42 
 43 #define PPP_VERSION     "2.4.1"
 44 
 45 #define OBUFSIZE        256
 46 
 47 /* Structure for storing local state. */
 48 struct asyncppp {
 49         struct tty_struct *tty;
 50         unsigned int    flags;
 51         unsigned int    state;
 52         unsigned int    rbits;
 53         int             mru;
 54         spinlock_t      xmit_lock;
 55         spinlock_t      recv_lock;
 56         unsigned long   xmit_flags;
 57         u32             xaccm[8];
 58         u32             raccm;
 59         unsigned int    bytes_sent;
 60         unsigned int    bytes_rcvd;
 61 
 62         struct sk_buff  *tpkt;
 63         int             tpkt_pos;
 64         u16             tfcs;
 65         unsigned char   *optr;
 66         unsigned char   *olim;
 67         unsigned long   last_xmit;
 68 
 69         struct sk_buff  *rpkt;
 70         int             lcp_fcs;
 71 
 72         struct ppp_channel chan;        /* interface to generic ppp layer */
 73         unsigned char   obuf[OBUFSIZE];
 74 };
 75 
 76 /* Bit numbers in xmit_flags */
 77 #define XMIT_WAKEUP     0
 78 #define XMIT_FULL       1
 79 
 80 /* State bits */
 81 #define SC_TOSS         0x20000000
 82 #define SC_ESCAPE       0x40000000
 83 
 84 /* Bits in rbits */
 85 #define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
 86 
 87 static int flag_time = HZ;
 88 MODULE_PARM(flag_time, "i");
 89 
 90 /*
 91  * Prototypes.
 92  */
 93 static int ppp_async_encode(struct asyncppp *ap);
 94 static int ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb);
 95 static int ppp_async_push(struct asyncppp *ap);
 96 static void ppp_async_flush_output(struct asyncppp *ap);
 97 static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
 98                             char *flags, int count);
 99 static int ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd,
100                            unsigned long arg);
101 static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
102                            int len, int inbound);
103 
104 struct ppp_channel_ops async_ops = {
105         ppp_async_send,
106         ppp_async_ioctl
107 };
108 
109 /*
110  * Routines implementing the PPP line discipline.
111  */
112 
113 /*
114  * Called when a tty is put into PPP line discipline.
115  */
116 static int
117 ppp_asynctty_open(struct tty_struct *tty)
118 {
119         struct asyncppp *ap;
120         int err;
121 
122         MOD_INC_USE_COUNT;
123         err = -ENOMEM;
124         ap = kmalloc(sizeof(*ap), GFP_KERNEL);
125         if (ap == 0)
126                 goto out;
127 
128         /* initialize the asyncppp structure */
129         memset(ap, 0, sizeof(*ap));
130         ap->tty = tty;
131         ap->mru = PPP_MRU;
132         spin_lock_init(&ap->xmit_lock);
133         spin_lock_init(&ap->recv_lock);
134         ap->xaccm[0] = ~0U;
135         ap->xaccm[3] = 0x60000000U;
136         ap->raccm = ~0U;
137         ap->optr = ap->obuf;
138         ap->olim = ap->obuf;
139         ap->lcp_fcs = -1;
140 
141         ap->chan.private = ap;
142         ap->chan.ops = &async_ops;
143         ap->chan.mtu = PPP_MRU;
144         err = ppp_register_channel(&ap->chan);
145         if (err)
146                 goto out_free;
147 
148         tty->disc_data = ap;
149 
150         return 0;
151 
152  out_free:
153         kfree(ap);
154  out:
155         MOD_DEC_USE_COUNT;
156         return err;
157 }
158 
159 /*
160  * Called when the tty is put into another line discipline
161  * or it hangs up.
162  * We assume that while we are in this routine, the tty layer
163  * won't call any of the other line discipline entries for the
164  * same tty.
165  */
166 static void
167 ppp_asynctty_close(struct tty_struct *tty)
168 {
169         struct asyncppp *ap = tty->disc_data;
170 
171         if (ap == 0)
172                 return;
173         tty->disc_data = 0;
174         ppp_unregister_channel(&ap->chan);
175         if (ap->rpkt != 0)
176                 kfree_skb(ap->rpkt);
177         if (ap->tpkt != 0)
178                 kfree_skb(ap->tpkt);
179         kfree(ap);
180         MOD_DEC_USE_COUNT;
181 }
182 
183 /*
184  * Read does nothing.
185  */
186 static ssize_t
187 ppp_asynctty_read(struct tty_struct *tty, struct file *file,
188                   unsigned char *buf, size_t count)
189 {
190         /* For now, do the same as the old 2.3.x code useta */
191         struct asyncppp *ap = tty->disc_data;
192 
193         if (ap == 0)
194                 return -ENXIO;
195         return ppp_channel_read(&ap->chan, file, buf, count);
196 }
197 
198 /*
199  * Write on the tty does nothing, the packets all come in
200  * from the ppp generic stuff.
201  */
202 static ssize_t
203 ppp_asynctty_write(struct tty_struct *tty, struct file *file,
204                    const unsigned char *buf, size_t count)
205 {
206         /* For now, do the same as the old 2.3.x code useta */
207         struct asyncppp *ap = tty->disc_data;
208 
209         if (ap == 0)
210                 return -ENXIO;
211         return ppp_channel_write(&ap->chan, buf, count);
212 }
213 
214 static int
215 ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
216                    unsigned int cmd, unsigned long arg)
217 {
218         struct asyncppp *ap = tty->disc_data;
219         int err, val;
220 
221         err = -EFAULT;
222         switch (cmd) {
223         case PPPIOCGCHAN:
224                 err = -ENXIO;
225                 if (ap == 0)
226                         break;
227                 err = -EFAULT;
228                 if (put_user(ppp_channel_index(&ap->chan), (int *) arg))
229                         break;
230                 err = 0;
231                 break;
232 
233         case PPPIOCGUNIT:
234                 err = -ENXIO;
235                 if (ap == 0)
236                         break;
237                 err = -EFAULT;
238                 if (put_user(ppp_unit_number(&ap->chan), (int *) arg))
239                         break;
240                 err = 0;
241                 break;
242 
243         case TCGETS:
244         case TCGETA:
245                 err = n_tty_ioctl(tty, file, cmd, arg);
246                 break;
247 
248         case TCFLSH:
249                 /* flush our buffers and the serial port's buffer */
250                 if (arg == TCIOFLUSH || arg == TCOFLUSH)
251                         ppp_async_flush_output(ap);
252                 err = n_tty_ioctl(tty, file, cmd, arg);
253                 break;
254 
255         case FIONREAD:
256                 val = 0;
257                 if (put_user(val, (int *) arg))
258                         break;
259                 err = 0;
260                 break;
261 
262 /*
263  * For now, do the same as the old 2.3 driver useta
264  */
265         case PPPIOCGFLAGS:
266         case PPPIOCSFLAGS:
267         case PPPIOCGASYNCMAP:
268         case PPPIOCSASYNCMAP:
269         case PPPIOCGRASYNCMAP:
270         case PPPIOCSRASYNCMAP:
271         case PPPIOCGXASYNCMAP:
272         case PPPIOCSXASYNCMAP:
273         case PPPIOCGMRU:
274         case PPPIOCSMRU:
275                 err = -EPERM;
276                 if (!capable(CAP_NET_ADMIN))
277                         break;
278                 err = ppp_async_ioctl(&ap->chan, cmd, arg);
279                 break;
280 
281         case PPPIOCATTACH:
282         case PPPIOCDETACH:
283                 err = ppp_channel_ioctl(&ap->chan, cmd, arg);
284                 break;
285 
286         default:
287                 err = -ENOIOCTLCMD;
288         }
289 
290         return err;
291 }
292 
293 /* No kernel lock - fine */
294 static unsigned int
295 ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
296 {
297         unsigned int mask;
298         struct asyncppp *ap = tty->disc_data;
299 
300         mask = POLLOUT | POLLWRNORM;
301 /*
302  * For now, do the same as the old 2.3 driver useta
303  */
304         if (ap != 0)
305                 mask |= ppp_channel_poll(&ap->chan, file, wait);
306         if (test_bit(TTY_OTHER_CLOSED, &tty->flags) || tty_hung_up_p(file))
307                 mask |= POLLHUP;
308         return mask;
309 }
310 
311 static int
312 ppp_asynctty_room(struct tty_struct *tty)
313 {
314         return 65535;
315 }
316 
317 static void
318 ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
319                   char *flags, int count)
320 {
321         struct asyncppp *ap = tty->disc_data;
322 
323         if (ap == 0)
324                 return;
325         spin_lock_bh(&ap->recv_lock);
326         ppp_async_input(ap, buf, flags, count);
327         spin_unlock_bh(&ap->recv_lock);
328         if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
329             && tty->driver.unthrottle)
330                 tty->driver.unthrottle(tty);
331 }
332 
333 static void
334 ppp_asynctty_wakeup(struct tty_struct *tty)
335 {
336         struct asyncppp *ap = tty->disc_data;
337 
338         clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
339         if (ap == 0)
340                 return;
341         if (ppp_async_push(ap))
342                 ppp_output_wakeup(&ap->chan);
343 }
344 
345 
346 static struct tty_ldisc ppp_ldisc = {
347         magic:  TTY_LDISC_MAGIC,
348         name:   "ppp",
349         open:   ppp_asynctty_open,
350         close:  ppp_asynctty_close,
351         read:   ppp_asynctty_read,
352         write:  ppp_asynctty_write,
353         ioctl:  ppp_asynctty_ioctl,
354         poll:   ppp_asynctty_poll,
355         receive_room: ppp_asynctty_room,
356         receive_buf: ppp_asynctty_receive,
357         write_wakeup: ppp_asynctty_wakeup,
358 };
359 
360 int
361 ppp_async_init(void)
362 {
363         int err;
364 
365         err = tty_register_ldisc(N_PPP, &ppp_ldisc);
366         if (err != 0)
367                 printk(KERN_ERR "PPP_async: error %d registering line disc.\n",
368                        err);
369         return err;
370 }
371 
372 /*
373  * The following routines provide the PPP channel interface.
374  */
375 static int
376 ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
377 {
378         struct asyncppp *ap = chan->private;
379         int err, val;
380         u32 accm[8];
381 
382         err = -EFAULT;
383         switch (cmd) {
384         case PPPIOCGFLAGS:
385                 val = ap->flags | ap->rbits;
386                 if (put_user(val, (int *) arg))
387                         break;
388                 err = 0;
389                 break;
390         case PPPIOCSFLAGS:
391                 if (get_user(val, (int *) arg))
392                         break;
393                 ap->flags = val & ~SC_RCV_BITS;
394                 spin_lock_bh(&ap->recv_lock);
395                 ap->rbits = val & SC_RCV_BITS;
396                 spin_unlock_bh(&ap->recv_lock);
397                 err = 0;
398                 break;
399 
400         case PPPIOCGASYNCMAP:
401                 if (put_user(ap->xaccm[0], (u32 *) arg))
402                         break;
403                 err = 0;
404                 break;
405         case PPPIOCSASYNCMAP:
406                 if (get_user(ap->xaccm[0], (u32 *) arg))
407                         break;
408                 err = 0;
409                 break;
410 
411         case PPPIOCGRASYNCMAP:
412                 if (put_user(ap->raccm, (u32 *) arg))
413                         break;
414                 err = 0;
415                 break;
416         case PPPIOCSRASYNCMAP:
417                 if (get_user(ap->raccm, (u32 *) arg))
418                         break;
419                 err = 0;
420                 break;
421 
422         case PPPIOCGXASYNCMAP:
423                 if (copy_to_user((void *) arg, ap->xaccm, sizeof(ap->xaccm)))
424                         break;
425                 err = 0;
426                 break;
427         case PPPIOCSXASYNCMAP:
428                 if (copy_from_user(accm, (void *) arg, sizeof(accm)))
429                         break;
430                 accm[2] &= ~0x40000000U;        /* can't escape 0x5e */
431                 accm[3] |= 0x60000000U;         /* must escape 0x7d, 0x7e */
432                 memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
433                 err = 0;
434                 break;
435 
436         case PPPIOCGMRU:
437                 if (put_user(ap->mru, (int *) arg))
438                         break;
439                 err = 0;
440                 break;
441         case PPPIOCSMRU:
442                 if (get_user(val, (int *) arg))
443                         break;
444                 if (val < PPP_MRU)
445                         val = PPP_MRU;
446                 ap->mru = val;
447                 err = 0;
448                 break;
449 
450         default:
451                 err = -ENOTTY;
452         }
453 
454         return err;
455 }
456 
457 /*
458  * Procedures for encapsulation and framing.
459  */
460 
461 u16 ppp_crc16_table[256] = {
462         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
463         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
464         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
465         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
466         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
467         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
468         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
469         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
470         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
471         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
472         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
473         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
474         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
475         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
476         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
477         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
478         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
479         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
480         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
481         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
482         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
483         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
484         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
485         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
486         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
487         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
488         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
489         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
490         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
491         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
492         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
493         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
494 };
495 EXPORT_SYMBOL(ppp_crc16_table);
496 #define fcstab  ppp_crc16_table         /* for PPP_FCS macro */
497 
498 /*
499  * Procedure to encode the data for async serial transmission.
500  * Does octet stuffing (escaping), puts the address/control bytes
501  * on if A/C compression is disabled, and does protocol compression.
502  * Assumes ap->tpkt != 0 on entry.
503  * Returns 1 if we finished the current frame, 0 otherwise.
504  */
505 
506 #define PUT_BYTE(ap, buf, c, islcp)     do {            \
507         if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\
508                 *buf++ = PPP_ESCAPE;                    \
509                 *buf++ = c ^ 0x20;                      \
510         } else                                          \
511                 *buf++ = c;                             \
512 } while (0)
513 
514 static int
515 ppp_async_encode(struct asyncppp *ap)
516 {
517         int fcs, i, count, c, proto;
518         unsigned char *buf, *buflim;
519         unsigned char *data;
520         int islcp;
521 
522         buf = ap->obuf;
523         ap->olim = buf;
524         ap->optr = buf;
525         i = ap->tpkt_pos;
526         data = ap->tpkt->data;
527         count = ap->tpkt->len;
528         fcs = ap->tfcs;
529         proto = (data[0] << 8) + data[1];
530 
531         /*
532          * LCP packets with code values between 1 (configure-reqest)
533          * and 7 (code-reject) must be sent as though no options
534          * had been negotiated.
535          */
536         islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
537 
538         if (i == 0) {
539                 if (islcp)
540                         async_lcp_peek(ap, data, count, 0);
541 
542                 /*
543                  * Start of a new packet - insert the leading FLAG
544                  * character if necessary.
545                  */
546                 if (islcp || flag_time == 0
547                     || jiffies - ap->last_xmit >= flag_time)
548                         *buf++ = PPP_FLAG;
549                 ap->last_xmit = jiffies;
550                 fcs = PPP_INITFCS;
551 
552                 /*
553                  * Put in the address/control bytes if necessary
554                  */
555                 if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
556                         PUT_BYTE(ap, buf, 0xff, islcp);
557                         fcs = PPP_FCS(fcs, 0xff);
558                         PUT_BYTE(ap, buf, 0x03, islcp);
559                         fcs = PPP_FCS(fcs, 0x03);
560                 }
561         }
562 
563         /*
564          * Once we put in the last byte, we need to put in the FCS
565          * and closing flag, so make sure there is at least 7 bytes
566          * of free space in the output buffer.
567          */
568         buflim = ap->obuf + OBUFSIZE - 6;
569         while (i < count && buf < buflim) {
570                 c = data[i++];
571                 if (i == 1 && c == 0 && (ap->flags & SC_COMP_PROT))
572                         continue;       /* compress protocol field */
573                 fcs = PPP_FCS(fcs, c);
574                 PUT_BYTE(ap, buf, c, islcp);
575         }
576 
577         if (i < count) {
578                 /*
579                  * Remember where we are up to in this packet.
580                  */
581                 ap->olim = buf;
582                 ap->tpkt_pos = i;
583                 ap->tfcs = fcs;
584                 return 0;
585         }
586 
587         /*
588          * We have finished the packet.  Add the FCS and flag.
589          */
590         fcs = ~fcs;
591         c = fcs & 0xff;
592         PUT_BYTE(ap, buf, c, islcp);
593         c = (fcs >> 8) & 0xff;
594         PUT_BYTE(ap, buf, c, islcp);
595         *buf++ = PPP_FLAG;
596         ap->olim = buf;
597 
598         kfree_skb(ap->tpkt);
599         ap->tpkt = 0;
600         return 1;
601 }
602 
603 /*
604  * Transmit-side routines.
605  */
606 
607 /*
608  * Send a packet to the peer over an async tty line.
609  * Returns 1 iff the packet was accepted.
610  * If the packet was not accepted, we will call ppp_output_wakeup
611  * at some later time.
612  */
613 static int
614 ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb)
615 {
616         struct asyncppp *ap = chan->private;
617 
618         ppp_async_push(ap);
619 
620         if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags))
621                 return 0;       /* already full */
622         ap->tpkt = skb;
623         ap->tpkt_pos = 0;
624 
625         ppp_async_push(ap);
626         return 1;
627 }
628 
629 /*
630  * Push as much data as possible out to the tty.
631  */
632 static int
633 ppp_async_push(struct asyncppp *ap)
634 {
635         int avail, sent, done = 0;
636         struct tty_struct *tty = ap->tty;
637         int tty_stuffed = 0;
638 
639         set_bit(XMIT_WAKEUP, &ap->xmit_flags);
640         if (!spin_trylock_bh(&ap->xmit_lock))
641                 return 0;
642         for (;;) {
643                 if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
644                         tty_stuffed = 0;
645                 if (!tty_stuffed && ap->optr < ap->olim) {
646                         avail = ap->olim - ap->optr;
647                         set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
648                         sent = tty->driver.write(tty, 0, ap->optr, avail);
649                         if (sent < 0)
650                                 goto flush;     /* error, e.g. loss of CD */
651                         ap->optr += sent;
652                         if (sent < avail)
653                                 tty_stuffed = 1;
654                         continue;
655                 }
656                 if (ap->optr == ap->olim && ap->tpkt != 0) {
657                         if (ppp_async_encode(ap)) {
658                                 /* finished processing ap->tpkt */
659                                 clear_bit(XMIT_FULL, &ap->xmit_flags);
660                                 done = 1;
661                         }
662                         continue;
663                 }
664                 /* haven't made any progress */
665                 spin_unlock_bh(&ap->xmit_lock);
666                 if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags)
667                       || (!tty_stuffed && ap->tpkt != 0)))
668                         break;
669                 if (!spin_trylock_bh(&ap->xmit_lock))
670                         break;
671         }
672         return done;
673 
674 flush:
675         if (ap->tpkt != 0) {
676                 kfree_skb(ap->tpkt);
677                 ap->tpkt = 0;
678                 clear_bit(XMIT_FULL, &ap->xmit_flags);
679                 done = 1;
680         }
681         ap->optr = ap->olim;
682         spin_unlock_bh(&ap->xmit_lock);
683         return done;
684 }
685 
686 /*
687  * Flush output from our internal buffers.
688  * Called for the TCFLSH ioctl.
689  */
690 static void
691 ppp_async_flush_output(struct asyncppp *ap)
692 {
693         int done = 0;
694 
695         spin_lock_bh(&ap->xmit_lock);
696         ap->optr = ap->olim;
697         if (ap->tpkt != NULL) {
698                 kfree_skb(ap->tpkt);
699                 ap->tpkt = 0;
700                 clear_bit(XMIT_FULL, &ap->xmit_flags);
701                 done = 1;
702         }
703         spin_unlock_bh(&ap->xmit_lock);
704         if (done)
705                 ppp_output_wakeup(&ap->chan);
706 }
707 
708 /*
709  * Receive-side routines.
710  */
711 
712 /* see how many ordinary chars there are at the start of buf */
713 static inline int
714 scan_ordinary(struct asyncppp *ap, const unsigned char *buf, int count)
715 {
716         int i, c;
717 
718         for (i = 0; i < count; ++i) {
719                 c = buf[i];
720                 if (c == PPP_ESCAPE || c == PPP_FLAG
721                     || (c < 0x20 && (ap->raccm & (1 << c)) != 0))
722                         break;
723         }
724         return i;
725 }
726 
727 /* called when a flag is seen - do end-of-packet processing */
728 static inline void
729 process_input_packet(struct asyncppp *ap)
730 {
731         struct sk_buff *skb;
732         unsigned char *p;
733         unsigned int len, fcs, proto;
734         int code = 0;
735 
736         skb = ap->rpkt;
737         ap->rpkt = 0;
738         if ((ap->state & (SC_TOSS | SC_ESCAPE)) || skb == 0) {
739                 ap->state &= ~(SC_TOSS | SC_ESCAPE);
740                 if (skb != 0)
741                         kfree_skb(skb);
742                 return;
743         }
744 
745         /* check the FCS */
746         p = skb->data;
747         len = skb->len;
748         if (len < 3)
749                 goto err;       /* too short */
750         fcs = PPP_INITFCS;
751         for (; len > 0; --len)
752                 fcs = PPP_FCS(fcs, *p++);
753         if (fcs != PPP_GOODFCS)
754                 goto err;       /* bad FCS */
755         skb_trim(skb, skb->len - 2);
756 
757         /* check for address/control and protocol compression */
758         p = skb->data;
759         if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
760                 /* chop off address/control */
761                 if (skb->len < 3)
762                         goto err;
763                 p = skb_pull(skb, 2);
764         }
765         proto = p[0];
766         if (proto & 1) {
767                 /* protocol is compressed */
768                 skb_push(skb, 1)[0] = 0;
769         } else {
770                 if (skb->len < 2)
771                         goto err;
772                 proto = (proto << 8) + p[1];
773                 if (proto == PPP_LCP)
774                         async_lcp_peek(ap, p, skb->len, 1);
775         }
776 
777         /* all OK, give it to the generic layer */
778         ppp_input(&ap->chan, skb);
779         return;
780 
781  err:
782         kfree_skb(skb);
783         ppp_input_error(&ap->chan, code);
784 }
785 
786 static inline void
787 input_error(struct asyncppp *ap, int code)
788 {
789         ap->state |= SC_TOSS;
790         ppp_input_error(&ap->chan, code);
791 }
792 
793 /* called when the tty driver has data for us. */
794 static void
795 ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
796                 char *flags, int count)
797 {
798         struct sk_buff *skb;
799         int c, i, j, n, s, f;
800         unsigned char *sp;
801 
802         /* update bits used for 8-bit cleanness detection */
803         if (~ap->rbits & SC_RCV_BITS) {
804                 s = 0;
805                 for (i = 0; i < count; ++i) {
806                         c = buf[i];
807                         if (flags != 0 && flags[i] != 0)
808                                 continue;
809                         s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0;
810                         c = ((c >> 4) ^ c) & 0xf;
811                         s |= (0x6996 & (1 << c))? SC_RCV_ODDP: SC_RCV_EVNP;
812                 }
813                 ap->rbits |= s;
814         }
815 
816         while (count > 0) {
817                 /* scan through and see how many chars we can do in bulk */
818                 if ((ap->state & SC_ESCAPE) && buf[0] == PPP_ESCAPE)
819                         n = 1;
820                 else
821                         n = scan_ordinary(ap, buf, count);
822 
823                 f = 0;
824                 if (flags != 0 && (ap->state & SC_TOSS) == 0) {
825                         /* check the flags to see if any char had an error */
826                         for (j = 0; j < n; ++j)
827                                 if ((f = flags[j]) != 0)
828                                         break;
829                 }
830                 if (f != 0) {
831                         /* start tossing */
832                         input_error(ap, f);
833 
834                 } else if (n > 0 && (ap->state & SC_TOSS) == 0) {
835                         /* stuff the chars in the skb */
836                         skb = ap->rpkt;
837                         if (skb == 0) {
838                                 skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
839                                 if (skb == 0)
840                                         goto nomem;
841                                 /* Try to get the payload 4-byte aligned */
842                                 if (buf[0] != PPP_ALLSTATIONS)
843                                         skb_reserve(skb, 2 + (buf[0] & 1));
844                                 ap->rpkt = skb;
845                         }
846                         if (n > skb_tailroom(skb)) {
847                                 /* packet overflowed MRU */
848                                 input_error(ap, 1);
849                         } else {
850                                 sp = skb_put(skb, n);
851                                 memcpy(sp, buf, n);
852                                 if (ap->state & SC_ESCAPE) {
853                                         sp[0] ^= 0x20;
854                                         ap->state &= ~SC_ESCAPE;
855                                 }
856                         }
857                 }
858 
859                 if (n >= count)
860                         break;
861 
862                 c = buf[n];
863                 if (c == PPP_FLAG) {
864                         process_input_packet(ap);
865                 } else if (c == PPP_ESCAPE) {
866                         ap->state |= SC_ESCAPE;
867                 }
868                 /* otherwise it's a char in the recv ACCM */
869                 ++n;
870 
871                 buf += n;
872                 if (flags != 0)
873                         flags += n;
874                 count -= n;
875         }
876         return;
877 
878  nomem:
879         printk(KERN_ERR "PPPasync: no memory (input pkt)\n");
880         input_error(ap, 0);
881 }
882 
883 /*
884  * We look at LCP frames going past so that we can notice
885  * and react to the LCP configure-ack from the peer.
886  * In the situation where the peer has been sent a configure-ack
887  * already, LCP is up once it has sent its configure-ack
888  * so the immediately following packet can be sent with the
889  * configured LCP options.  This allows us to process the following
890  * packet correctly without pppd needing to respond quickly.
891  *
892  * We only respond to the received configure-ack if we have just
893  * sent a configure-request, and the configure-ack contains the
894  * same data (this is checked using a 16-bit crc of the data).
895  */
896 #define CONFREQ         1       /* LCP code field values */
897 #define CONFACK         2
898 #define LCP_MRU         1       /* LCP option numbers */
899 #define LCP_ASYNCMAP    2
900 
901 static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
902                            int len, int inbound)
903 {
904         int dlen, fcs, i, code;
905         u32 val;
906 
907         data += 2;              /* skip protocol bytes */
908         len -= 2;
909         if (len < 4)            /* 4 = code, ID, length */
910                 return;
911         code = data[0];
912         if (code != CONFACK && code != CONFREQ)
913                 return;
914         dlen = (data[2] << 8) + data[3];
915         if (len < dlen)
916                 return;         /* packet got truncated or length is bogus */
917 
918         if (code == (inbound? CONFACK: CONFREQ)) {
919                 /*
920                  * sent confreq or received confack:
921                  * calculate the crc of the data from the ID field on.
922                  */
923                 fcs = PPP_INITFCS;
924                 for (i = 1; i < dlen; ++i)
925                         fcs = PPP_FCS(fcs, data[i]);
926 
927                 if (!inbound) {
928                         /* outbound confreq - remember the crc for later */
929                         ap->lcp_fcs = fcs;
930                         return;
931                 }
932 
933                 /* received confack, check the crc */
934                 fcs ^= ap->lcp_fcs;
935                 ap->lcp_fcs = -1;
936                 if (fcs != 0)
937                         return;
938         } else if (inbound)
939                 return; /* not interested in received confreq */
940 
941         /* process the options in the confack */
942         data += 4;
943         dlen -= 4;
944         /* data[0] is code, data[1] is length */
945         while (dlen >= 2 && dlen >= data[1]) {
946                 switch (data[0]) {
947                 case LCP_MRU:
948                         val = (data[2] << 8) + data[3];
949                         if (inbound)
950                                 ap->mru = val;
951                         else
952                                 ap->chan.mtu = val;
953                         break;
954                 case LCP_ASYNCMAP:
955                         val = (data[2] << 24) + (data[3] << 16)
956                                 + (data[4] << 8) + data[5];
957                         if (inbound)
958                                 ap->raccm = val;
959                         else
960                                 ap->xaccm[0] = val;
961                         break;
962                 }
963                 dlen -= data[1];
964                 data += data[1];
965         }
966 }
967 
968 void __exit ppp_async_cleanup(void)
969 {
970         if (tty_register_ldisc(N_PPP, NULL) != 0)
971                 printk(KERN_ERR "failed to unregister PPP line discipline\n");
972 }
973 
974 module_init(ppp_async_init);
975 module_exit(ppp_async_cleanup);
976 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.