1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
/*
* $Id$
*
* Get the device used for the tunnel in a portable way
*
*/
#ifdef LINUX
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#include <unistd.h>
#endif /* LINUX */
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include "device.h"
#define MODULE_NAME "userlink"
#define DEVICES_FILE "/proc/devices"
#define INSMOD_COMMAND "/sbin/insmod -k %s"
#define RMMOD_COMMAND "/sbin/rmmod %s"
#define BSD_NAME "/dev/tun%d"
#ifdef USE_LINUX_TUNTAP
#define LINUX_NAME "/dev/net/tun"
#else
#define LINUX_NAME "/dev/ul%d"
#endif
#ifdef LINUX
static struct device {
int minor;
char *name;
struct device *next;
} *devhead;
static int get_major_from_devices (void);
static int get_major (void);
static int
get_major_from_devices ()
{
FILE *dev;
char devname[128];
int major;
dev = fopen (DEVICES_FILE, "r");
while (!feof (dev)) {
if (fscanf (dev, "%d %s", &major, devname) == 2) {
if (strcmp (devname, MODULE_NAME) == 0) {
syslog (LOG_INFO, "major for module %s is %d", MODULE_NAME, major);
return major;
}
} else {
fgets (devname, sizeof devname, dev);
}
}
fclose (dev);
return -1;
}
static int
get_major ()
{
char command [1024];
int major;
major = get_major_from_devices ();
if (major == -1) {
syslog (LOG_NOTICE, "loading userlink module");
sprintf (command, INSMOD_COMMAND, MODULE_NAME);
system (command);
major = get_major_from_devices ();
}
if (major == -1) syslog (LOG_ALERT, "unable to find major for module %s",
MODULE_NAME);
return major;
}
#endif /* LINUX */
char *
get_device (int minor)
{
char buffer[256];
char *devname;
#ifdef LINUX
#ifdef USE_LINUX_TUNTAP
return LINUX_NAME;
#else
struct device *current;
int major;
for (current = devhead; current; current = current->next)
if (current->minor == minor) return current->name;
major = get_major ();
if (major == -1)
return NULL;
sprintf (buffer, LINUX_NAME, minor);
unlink (buffer);
if (mknod (buffer, S_IFCHR | 0600, makedev (major, minor)) != 0)
return NULL;
#endif
#else
sprintf (buffer, BSD_NAME, minor);
#endif
devname = malloc (strlen (buffer));
strcpy (devname, buffer);
#ifdef LINUX
#ifndef USE_LINUX_TUNTAP
current = (struct device *) malloc (sizeof (struct device));
current->minor = minor;
current->name = devname;
current->next = devhead;
devhead = current;
#endif
#endif
return devname;
}
char *
get_full_device (char *name)
{
char *current;
for (current = name; *current; current++) {
if (*current < '0' || *current > '9') return name;
}
return get_device (atoi (name));
}
|