Patch for Naming of PPP Devices

Henning P. Schmiedehausen (hps@tanstaafl.de)
12 Nov 1997 19:14:05 +0100


This is a patch for Linux 2.0.29 which fixes a problem that I always
had with PPP Devices: They change names. I use Linux to drive some
leased lines and whenever I reboot, the lines come up with different
names. This is because of the dynamic name allocation of the PPP
device.

This patch fixes the allocation. ppp0 is always on ttyS0, ppp1 on
ttyS1 and so on. Other devices (e.g. on a pty) are still allocated
dynamic but from ppp64 and further.

You need also a patch to the pppd because this brain dead thing tries
to open ppp0 to check whether ppp support is in the kernel. This will
fail if you don't run PPP on ttyS0.

I use this patch in production for some weeks with exact the wanted
effect.

Maybe this patch is useful to some other people.

Kind regards
Henning

P.S.: Yeah, Linus, I know this is not in the correct (TM) Linux
indenting style. If someone wants to fix this: Go ahead.

--- cut --- kernel-patch --- cut ---
diff -Nurb linux-2.0.29/drivers/net/ppp.c linux-2.0.29.p/drivers/net/ppp.c
--- linux-2.0.29/drivers/net/ppp.c Sun Nov 10 21:54:06 1996
+++ linux-2.0.29.p/drivers/net/ppp.c Mon Nov 3 14:20:26 1997
@@ -51,6 +51,8 @@
#define PPP_MAX_DEV 256
#endif

+#define PPP_SERIAL_DEV 64 /* We allocate 64 Devices for our serial ports */
+
/* $Id: ppp.c,v 1.5 1995/06/12 11:36:53 paulus Exp $
* Added dynamic allocation of channels to eliminate
* compiled-in limits on the number of channels.
@@ -74,6 +76,7 @@
#include <linux/sched.h> /* to get the struct task_struct */
#include <linux/string.h> /* used in new tty drivers */
#include <linux/signal.h> /* used in new tty drivers */
+#include <linux/major.h> /* for serial port allocation */
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/segment.h>
@@ -126,8 +129,8 @@
static void ppp_init_ctrl_blk (register struct ppp *);
static void ppp_kick_tty (struct ppp *, struct ppp_buffer *bfr);
static int ppp_doframe (struct ppp *);
-static struct ppp *ppp_alloc (void);
-static struct ppp *ppp_find (int pid_value);
+static struct ppp *ppp_alloc (int, short);
+static struct ppp *ppp_find (int pid_value, int, short);
static void ppp_print_buffer (const __u8 *, const __u8 *, int);
extern inline void ppp_stuff_char (struct ppp *ppp,
register struct ppp_buffer *buf,
@@ -769,6 +772,16 @@
{
struct ppp *ppp = tty2ppp (tty);
int indx;
+ int on_serial = 0;
+ int minor = MINOR(tty->device) - tty->driver.minor_start + tty->driver.name_base;
+
+
+ if ((tty->driver.major == TTY_MAJOR) && (tty->driver.type == TTY_DRIVER_TYPE_SERIAL)) {
+ printk (KERN_INFO "PPP: Serial device detected!\n");
+ on_serial = 1;
+ }
+
+
/*
* There should not be an existing table for this slot.
*/
@@ -783,11 +796,12 @@
/*
* Allocate the structure from the system
*/
- ppp = ppp_find(current->pid);
+ ppp = ppp_find(current->pid, on_serial, minor);
+ if (ppp == NULL) {
+ ppp = ppp_find(0, on_serial, minor);
if (ppp == NULL) {
- ppp = ppp_find(0);
- if (ppp == NULL)
- ppp = ppp_alloc();
+ ppp = ppp_alloc(on_serial, minor);
+ }
}

if (ppp == NULL) {
@@ -3169,7 +3183,7 @@

/* Locate the previous instance of the PPP channel */
static struct ppp *
-ppp_find (int pid_value)
+ppp_find (int pid_value, int on_serial, short minor)
{
int if_num;
ppp_ctrl_t *ctl;
@@ -3183,9 +3197,26 @@
ppp = ctl2ppp (ctl);
if (!set_bit(0, &ppp->inuse)) {
if (ppp->sc_xfer == pid_value) {
+ if(pid_value) {
+ ppp->sc_xfer = 0;
+ return (ppp);
+ } else {
+ if(on_serial) {
+ if(minor == ppp->line) {
+ ppp->sc_xfer = 0;
+ return (ppp);
+ }
+ }
+ else
+ {
+ if(ppp->line >= PPP_SERIAL_DEV)
+ {
ppp->sc_xfer = 0;
return (ppp);
}
+ }
+ }
+ }
clear_bit (0, &ppp->inuse);
}
ctl = ctl->next;
@@ -3197,7 +3228,7 @@

/* allocate or create a PPP channel */
static struct ppp *
-ppp_alloc (void)
+ppp_alloc (int on_serial, short fix_num)
{
int if_num;
int status;
@@ -3208,15 +3239,33 @@
/* try to find an free device */
ctl = ppp_list;
if_num = 0;
+ float_num = PPP_SERIAL_DEV;

while (ctl) {
ppp = ctl2ppp (ctl);
- if (!set_bit(0, &ppp->inuse))
+ if (!set_bit(0, &ppp->inuse)) {
+ if(on_serial) {
+ if(fix_num == ppp->line) {
return (ppp);
+ }
+ } else {
+ if(ppp->line >= PPP_SERIAL_DEV)
+ {
+ return(ppp);
+ }
+ }
+ }
ctl = ctl->next;
+ float_num++;
if (++if_num == max_dev)
return (NULL);
}
+
+ if(on_serial)
+ if_num = fix_num;
+ else
+ if_num = float_num;
+
/*
* There are no available items. Allocate a device from the system pool
*/
diff -Nurb linux-2.0.29/init/patches/ppp-patch linux-2.0.29.p/init/patches/ppp-patch
--- linux-2.0.29/init/patches/ppp-patch Thu Jan 1 01:00:00 1970
+++ linux-2.0.29.p/init/patches/ppp-patch Mon Nov 3 14:04:55 1997
@@ -0,0 +1 @@
+PPP Fixed Devices
--- cut --- kernel-patch --- cut ---

--- cut --- daemon-patch --- cut ---
diff -Nurb ppp-2.2.0g/pppd/sys-linux.c ppp-2.2.0g.p/pppd/sys-linux.c
--- ppp-2.2.0g/pppd/sys-linux.c Sat Apr 13 07:02:53 1996
+++ ppp-2.2.0g.p/pppd/sys-linux.c Mon Nov 3 14:00:17 1997
@@ -1612,108 +1612,7 @@

int ppp_available(void)
{
- int s, ok;
- struct ifreq ifr;
- char abBuffer [1024];
- int size;
- int my_version, my_modification, my_patch;
-/*
- * Open a socket for doing the ioctl operations.
- */
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- {
- return 0;
- }
-
- strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
- ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
-/*
- * If the device did not exist then attempt to create one by putting the
- * current tty into the PPP discipline. If this works then obtain the
- * flags for the device again.
- */
- if (!ok)
- {
- if (ppp_registered())
- {
- strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
- ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
- }
- }
-/*
- * Ensure that the hardware address is for PPP and not something else
- */
- if (ok)
- {
- ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
- }
-
- if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
- {
- ok = 0;
- }
-
- if (!ok)
- {
- return 0;
- }
-/*
- * This is the PPP device. Validate the version of the driver at this
- * point to ensure that this program will work with the driver.
- */
- ifr.ifr_data = abBuffer;
- size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
- ok = size >= 0;
-
- if (ok)
- {
- decode_version (abBuffer,
- &driver_version,
- &driver_modification,
- &driver_patch);
- }
-
- if (!ok)
- {
- driver_version =
- driver_modification =
- driver_patch = 0;
- }
-/*
- * Validate the version of the driver against the version that we used.
- */
- decode_version (PPP_VERSION,
- &my_version,
- &my_modification,
- &my_patch);
-
- /* The version numbers must match */
- if (driver_version != my_version)
- {
- ok = 0;
- }
-
- /* The modification levels must be legal */
- if (driver_modification < my_modification)
- {
- ok = 0;
- }
-
- if (!ok)
- {
- extern char *no_ppp_msg;
-
- no_ppp_msg = route_buffer;
-
- sprintf(no_ppp_msg,
- "Sorry - PPP driver version %d.%d.%d is out of date\n",
- driver_version, driver_modification, driver_patch);
- ok = 0;
- }
-
- close(s);
- return ok;
+ return 1;
}

/*
--- cut --- daemon-patch --- cut ---

-- 
Dipl.-Inf. Henning P. Schmiedehausen --         priv: henning@forge.franken.de
TANSTAAFL! Consulting - Unix, Internet, Security       ges:   hps@tanstaafl.de 

Westl. Stadtmauerstrasse 52 Tel.: 09131 / 81297-0 "There ain't no such D-91054 Erlangen Fax.: 09131 / 81297-20 thing as a free lunch"