File: device.c

package info (click to toggle)
pipsecd 1%3A19990511-27
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 284 kB
  • ctags: 272
  • sloc: ansic: 2,183; perl: 1,836; sh: 82; makefile: 41
file content (130 lines) | stat: -rw-r--r-- 2,746 bytes parent folder | download | duplicates (3)
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));
}