-static int
-make_openvswitch_device(int minor, char **fnp)
-{
- const char dirname[] = "/dev/net";
- int major;
- dev_t dev;
- struct stat s;
- char fn[128];
-
- *fnp = NULL;
-
- major = get_openvswitch_major();
- if (major < 0) {
- return -major;
- }
- dev = makedev(major, minor);
-
- sprintf(fn, "%s/dp%d", dirname, minor);
- if (!stat(fn, &s)) {
- if (!S_ISCHR(s.st_mode)) {
- VLOG_WARN_RL(&error_rl, "%s is not a character device, fixing",
- fn);
- } else if (s.st_rdev != dev) {
- VLOG_WARN_RL(&error_rl,
- "%s is device %u:%u but should be %u:%u, fixing",
- fn, major(s.st_rdev), minor(s.st_rdev),
- major(dev), minor(dev));
- } else {
- goto success;
- }
- if (unlink(fn)) {
- VLOG_WARN_RL(&error_rl, "%s: unlink failed (%s)",
- fn, strerror(errno));
- return errno;
- }
- } else if (errno == ENOENT) {
- if (stat(dirname, &s)) {
- if (errno == ENOENT) {
- if (mkdir(dirname, 0755)) {
- VLOG_WARN_RL(&error_rl, "%s: mkdir failed (%s)",
- dirname, strerror(errno));
- return errno;
- }
- } else {
- VLOG_WARN_RL(&error_rl, "%s: stat failed (%s)",
- dirname, strerror(errno));
- return errno;
- }
- }
- } else {
- VLOG_WARN_RL(&error_rl, "%s: stat failed (%s)", fn, strerror(errno));
- return errno;
- }
-
- /* The device needs to be created. */
- if (mknod(fn, S_IFCHR | 0700, dev)) {
- VLOG_WARN_RL(&error_rl,
- "%s: creating character device %u:%u failed (%s)",
- fn, major(dev), minor(dev), strerror(errno));
- return errno;
- }
-
-success:
- *fnp = xstrdup(fn);
- return 0;
-}
-
-/* Return the major device number of the Open vSwitch device. If it
- * cannot be determined, a negative errno is returned. */
-static int
-get_openvswitch_major(void)
-{
- static int openvswitch_major = -1;
- if (openvswitch_major < 0) {
- openvswitch_major = get_major("openvswitch");
- }
- return openvswitch_major;
-}
-
-static int
-get_major(const char *target)
-{
- const char fn[] = "/proc/devices";
- char line[128];
- FILE *file;
- int ln;
-
- file = fopen(fn, "r");
- if (!file) {
- VLOG_ERR("opening %s failed (%s)", fn, strerror(errno));
- return -errno;
- }
-
- for (ln = 1; fgets(line, sizeof line, file); ln++) {
- char name[64];
- int major;
-
- if (!strncmp(line, "Character", 9) || line[0] == '\0') {
- /* Nothing to do. */
- } else if (!strncmp(line, "Block", 5)) {
- /* We only want character devices, so skip the rest of the file. */
- break;
- } else if (sscanf(line, "%d %63s", &major, name)) {
- if (!strcmp(name, target)) {
- fclose(file);
- return major;
- }
- } else {
- VLOG_WARN_ONCE("%s:%d: syntax error", fn, ln);
- }
- }
-
- fclose(file);
-
- VLOG_ERR("%s: %s major not found (is the module loaded?)", fn, target);
- return -ENODEV;
-}
-
-static int
-open_minor(int minor, int *fdp)
-{
- int error;
- char *fn;
-
- error = make_openvswitch_device(minor, &fn);
- if (error) {
- return error;
- }
-
- *fdp = open(fn, O_RDONLY | O_NONBLOCK);
- if (*fdp < 0) {
- error = errno;
- VLOG_WARN("%s: open failed (%s)", fn, strerror(error));
- free(fn);
- return error;
- }
- free(fn);
- return 0;
-}
-