/*
* Wireless Tools
*
- * Jean II - HPL 04
+ * Jean II - HPL 04 -> 07
*
* Main code for "ifrename". This is tool allows to rename network
* interfaces based on various criteria (not only wireless).
* You need to link this code against "iwlib.c" and "-lm".
*
* This file is released under the GPL license.
- * Copyright (c) 2004 Jean Tourrilhes <jt@hpl.hp.com>
+ * Copyright (c) 2007 Jean Tourrilhes <jt@hpl.hp.com>
*/
/*
* Difference with standard 'nameif' :
* o 'nameif' has only a single selector, the interface MAC address.
* o Modular selector architecture, easily add new selectors.
- * o Wide range of selector, including sysfs...
+ * o Wide range of selector, including sysfs and sysfs symlinks...
* o hotplug invocation support.
* o module loading support.
* o MAC address wildcard.
const int SELECT_IWPROTO = 10; /* Select by Wireless Protocol */
const int SELECT_PCMCIASLOT = 11; /* Select by Pcmcia Slot */
const int SELECT_SYSFS = 12; /* Select by sysfs file */
-#define SELECT_NUM 13
+const int SELECT_PREVNAME = 13; /* Select by previous interface name */
+#define SELECT_NUM 14
#define HAS_MAC_EXACT 1
#define HAS_MAC_FILTER 2
{"interface", 1, NULL, 'i' },
{"newname", 1, NULL, 'n' },
{"takeover", 0, NULL, 't' },
+ {"udev", 0, NULL, 'u' },
{"version", 0, NULL, 'v' },
{"verbose", 0, NULL, 'V' },
{NULL, 0, NULL, '\0' },
#define PCMCIA_STAB1 "/var/lib/pcmcia/stab"
#define PCMCIA_STAB2 "/var/run/stab"
-/* Max number of sysfs file we support */
-#define SYSFS_MAX_FILE 5
+/* Max number of sysfs file types we support */
+#define SYSFS_MAX_FILE 8
/* Userspace headers lag, fix that... */
#ifndef ARPHRD_IEEE1394
/* Name of this interface */
char ifname[IFNAMSIZ+1];
+ char * sysfs_devpath;
+ int sysfs_devplen;
/* Selectors for this interface */
int active[SELECT_NUM]; /* Selectors active */
char iwproto[IFNAMSIZ + 1]; /* Wireless/protocol name */
int pcmcia_slot; /* Pcmcia slot */
char * sysfs[SYSFS_MAX_FILE]; /* sysfs selectors */
+ char prevname[IFNAMSIZ+1]; /* previous interface name */
} if_mapping;
/* Extra parsing information when adding a mapping */
const char * ifname,
struct if_mapping * target,
int flag);
+static int
+ mapping_addprevname(struct if_mapping * ifnode,
+ int * active,
+ char * pos,
+ size_t len,
+ struct add_extra * extra,
+ int linenum);
+static int
+ mapping_cmpprevname(struct if_mapping * ifnode,
+ struct if_mapping * target);
+static int
+ mapping_getprevname(int skfd,
+ const char * ifname,
+ struct if_mapping * target,
+ int flag);
/**************************** VARIABLES ****************************/
{ "pcmciaslot", &mapping_addpcmciaslot, &mapping_cmppcmciaslot, &mapping_getpcmciaslot },
/* sysfs file (udev emulation) */
{ "sysfs", &mapping_addsysfs, &mapping_cmpsysfs, &mapping_getsysfs },
+ /* previous interface name */
+ { "prevname", &mapping_addprevname, &mapping_cmpprevname, &mapping_getprevname },
/* The Terminator */
{ NULL, NULL, NULL, NULL },
};
char * new_name = NULL;
/* Takeover support */
-int force_takeover = 0; /* Takeover name from other interface */
+int force_takeover = 0; /* Takeover name from other interfaces */
int num_takeover = 0; /* Number of takeover done */
+/* Number of mapping matched */
+int num_mapping_match = 0;
+
/* Dry-run support */
int dry_run = 0; /* Just print new name, don't rename */
/* Verbose support (i.e. debugging) */
int verbose = 0;
+/* udev output support (print new DEVPATH) */
+int udev_output = 0;
+
/* sysfs global data */
struct sysfs_metadata sysfs_global =
{
int n;
int ret;
- /* Check for a wildcard (converted from '*' to '%d' in mapping_create()) */
- p = strstr(pattern, "%d");
+ /* Check for a wildcard */
+ p = strchr(pattern, '*');
/* No wildcard, simple comparison */
if(p == NULL)
while(isdigit(*v));
/* Pattern suffix */
- p += 2;
+ p += 1;
/* Compare suffixes */
return(strcmp(p, v));
char * retname)
{
struct ifreq ifr;
+ char * star;
int ret;
/* The kernel doesn't check is the interface already has the correct
strncpy(ifr.ifr_name, oldname, IFNAMSIZ);
strncpy(ifr.ifr_newname, newname, IFNAMSIZ);
+ /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
+ * This require specific kernel support (2.6.2-rc1 and later).
+ * We externally use '*', but the kernel doesn't know about that,
+ * so convert it to something it knows about... */
+ star = strchr(newname, '*');
+ if(star != NULL)
+ {
+ int slen = star - newname;
+ /* Replace '*' with '%d' in the new buffer */
+ star = ifr.ifr_newname + slen;
+ /* Size was checked in process_rename() and mapping_create() */
+ memmove(star + 2, star + 1, IFNAMSIZ - slen - 2);
+ star[0] = '%';
+ star[1] = 'd';
+ }
+
/* Do it */
ret = ioctl(skfd, SIOCSIFNAME, &ifr);
/* Verify validity of string */
if(len >= sizeof(ifnode->mac_filter))
{
- fprintf(stderr, "MAC address too long at line %d\n", linenum);
+ fprintf(stderr, "Error : MAC address too long at line %d\n", linenum);
return(-1);
}
n = strspn(string, "0123456789ABCDEFabcdef:*");
int flag)
{
FILE * stream;
+ char * fname;
+ int fnsize;
char * linebuf = NULL;
size_t linelen = 0;
char * sdup;
skfd = skfd;
flag = flag;
- /* Check if we know the root of the sysfs filesystem */
- if(sysfs_global.root == NULL)
+ /* Check if we know the devpath of this device */
+ if(target->sysfs_devpath == NULL)
{
- /* Open the mount file for reading */
- stream = fopen("/proc/mounts", "r");
- if(!stream)
- {
- fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n",
- strerror(errno));
- return(-1);
- }
-
- /* Read each line of file
- * getline is a GNU extension :-( The buffer is recycled and increased
- * as needed by getline. */
- while(getline(&linebuf, &linelen, stream) > 0)
+ /* Check if we know the root of the sysfs filesystem */
+ if(sysfs_global.root == NULL)
{
- char * p;
- size_t n;
+ /* Open the mount file for reading */
+ stream = fopen("/proc/mounts", "r");
+ if(!stream)
+ {
+ fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n",
+ strerror(errno));
+ return(-1);
+ }
- /* Get the line starting with sysfs */
- p = linebuf;
- while(isspace(*p))
- ++p;
- if(!strncasecmp(p, "sysfs ", 6))
+ /* Read each line of file
+ * getline is a GNU extension :-( The buffer is recycled and
+ * increased as needed by getline. */
+ while(getline(&linebuf, &linelen, stream) > 0)
{
- /* Find the mount point */
- p += 6;
- while(isspace(*p))
- ++p;
- n = strcspn(p, " \t\n");
- sdup = strndup(p, n);
- if((n == 0) || (sdup == NULL))
+ int i;
+ char * p;
+ size_t n;
+ char * token[3];
+ size_t toklen[3];
+
+ /* The format of /proc/mounts is similar to /etc/fstab (5).
+ * The first argument is the device. For sysfs, there is no
+ * associated device, so this argument is ignored.
+ * The second argument is the mount point.
+ * The third argument is the filesystem type.
+ */
+
+ /* Extract the first 3 tokens */
+ p = linebuf;
+ for(i = 0; i < 3; i++)
{
- fprintf(stderr, "Error: Can't parse /proc/mounts file: %s\n",
- strerror(errno));
- return(-1);
+ while(isspace(*p))
+ ++p;
+ token[i] = p;
+ n = strcspn(p, " \t\n");
+ toklen[i] = n;
+ p += n;
}
- /* Store it */
- sysfs_global.root = sdup;
- sysfs_global.rlen = n;
- break;
+ /* Get the filesystem which type is "sysfs" */
+ if((n == 5) && (!strncasecmp(token[2], "sysfs", 5)))
+ {
+ /* Get its mount point */
+ n = toklen[1];
+ sdup = strndup(token[1], n);
+ if((n == 0) || (sdup == NULL))
+ {
+ fprintf(stderr,
+ "Error: Can't parse /proc/mounts file: %s\n",
+ strerror(errno));
+ return(-1);
+ }
+ /* Store it */
+ sysfs_global.root = sdup;
+ sysfs_global.rlen = n;
+ break;
+ }
+ /* Finished -> next line */
}
- /* Finished -> next line */
- }
- /* Cleanup */
- fclose(stream);
+ /* Cleanup */
+ fclose(stream);
- /* Check if we found it */
- if(sysfs_global.root == NULL)
+ /* Check if we found it */
+ if(sysfs_global.root == NULL)
+ {
+ fprintf(stderr,
+ "Error: Can't find sysfs in /proc/mounts file\n");
+ free(linebuf);
+ return(-1);
+ }
+ }
+
+ /* Construct devpath for this interface.
+ * Reserve enough space to replace name without realloc. */
+ fnsize = (sysfs_global.rlen + 11 + IFNAMSIZ + 1);
+ fname = malloc(fnsize);
+ if(fname == NULL)
{
- fprintf(stderr, "Error: Can't find sysfs in /proc/mounts file\n");
- free(linebuf);
+ fprintf(stderr, "Error: Can't allocate SYSFS devpath\n");
return(-1);
}
+ /* Not true devpath for 2.6.20+, but this syslink should work */
+ target->sysfs_devplen = sprintf(fname, "%s/class/net/%s",
+ sysfs_global.root, ifname);
+ target->sysfs_devpath = fname;
}
/* Loop on all sysfs selector */
for(findex = 0; findex < sysfs_global.filenum; findex++)
{
- char * fname;
- int flen;
char * p;
ssize_t n;
/* Construct complete filename for the sysfs selector */
- flen = (sysfs_global.rlen + 11 + strlen(ifname) + 1 +
- strlen(sysfs_global.filename[findex]) + 1);
- fname = malloc(flen);
+ fnsize = (target->sysfs_devplen + 1 +
+ strlen(sysfs_global.filename[findex]) + 1);
+ fname = malloc(fnsize);
if(fname == NULL)
{
fprintf(stderr, "Error: Can't allocate SYSFS filename\n");
free(linebuf);
return(-1);
}
- sprintf(fname, "%s/class/net/%s/%s", sysfs_global.root, ifname,
+ sprintf(fname, "%s/%s", target->sysfs_devpath,
sysfs_global.filename[findex]);
/* Open the sysfs file for reading */
fclose(stream);
if(n <= 0)
{
- /* Some sysfs attribute are void for some interface */
- if(verbose)
- fprintf(stderr, "Error: Can't read file `%s'\n", fname);
- /* Next sysfs selector */
- continue;
- }
+ /* Some attributes are just symlinks to another directory.
+ * We can read the attributes in that other directory
+ * just fine, but sometimes the symlink itself gives a lot
+ * of information.
+ * Examples : SYSFS{device} and SYSFS{device/driver}
+ * In such cases, get the name of the directory pointed to...
+ */
+ /*
+ * I must note that the API for readlink() is very bad,
+ * which force us to have this ugly code. Yuck !
+ */
+ int allocsize = 128; /* 256 = Good start */
+ int retry = 16;
+ char * linkpath = NULL;
+ int pathlen;
- /* Get content, remove trailing '/n', save it */
- p = linebuf;
- if(p[n - 1] == '\n')
- n--;
- sdup = strndup(p, n);
+ /* Try reading the link with increased buffer size */
+ do
+ {
+ allocsize *= 2;
+ linkpath = realloc(linkpath, allocsize);
+ pathlen = readlink(fname, linkpath, allocsize);
+ /* If we did not hit the buffer limit, success */
+ if(pathlen < allocsize)
+ break;
+ }
+ while(retry-- > 0);
+
+ /* Check for error, most likely ENOENT */
+ if(pathlen > 0)
+ /* We have a symlink ;-) Terminate the string. */
+ linkpath[pathlen] = '\0';
+ else
+ {
+ /* Error ! */
+ free(linkpath);
+
+ /* A lot of information in the sysfs is implicit, given
+ * by the position of a file in the tree. It is therefore
+ * important to be able to read the various components
+ * of a path. For this reason, we resolve '..' to the
+ * real name of the parent directory... */
+ /* We have at least 11 char, see above */
+ if(!strcmp(fname + fnsize - 4, "/.."))
+ //if(!strcmp(fname + strlen(fname) - 3, "/.."))
+ {
+ /* This procedure to get the realpath is not very
+ * nice, but it's the "best practice". Hmm... */
+ int cwd_fd = open(".", O_RDONLY);
+ linkpath = NULL;
+ if(cwd_fd > 0)
+ {
+ int ret = chdir(fname);
+ if(ret == 0)
+ /* Using getcwd with NULL is a GNU extension. Nice. */
+ linkpath = getcwd(NULL, 0);
+ /* This may fail, but it's not fatal */
+ fchdir(cwd_fd);
+ }
+ /* Check if we suceeded */
+ if(!linkpath)
+ {
+ free(linkpath);
+ if(verbose)
+ fprintf(stderr, "Error: Can't read parent directory `%s'\n", fname);
+ /* Next sysfs selector */
+ continue;
+ }
+ }
+ else
+ {
+ /* Some sysfs attribute are void for some interface,
+ * we may have a real directory, or we may have permission
+ * issues... */
+ if(verbose)
+ fprintf(stderr, "Error: Can't read file `%s'\n", fname);
+ /* Next sysfs selector */
+ continue;
+ }
+ }
+
+ /* Here, we have a link name or a parent directory name */
+
+ /* Keep only the last component of path name, save it */
+ p = basename(linkpath);
+ sdup = strdup(p);
+ free(linkpath);
+ }
+ else
+ {
+ /* This is a regular file (well, pseudo file) */
+ /* Get content, remove trailing '/n', save it */
+ p = linebuf;
+ if(p[n - 1] == '\n')
+ n--;
+ sdup = strndup(p, n);
+ }
if(sdup == NULL)
{
fprintf(stderr, "Error: Can't allocate SYSFS value\n");
return(target->active[SELECT_SYSFS] ? 0 : -1);
}
+/*------------------------------------------------------------------*/
+/*
+ * Add a Previous Interface Name selector to a mapping
+ */
+static int
+mapping_addprevname(struct if_mapping * ifnode,
+ int * active,
+ char * string,
+ size_t len,
+ struct add_extra * extra,
+ int linenum)
+{
+ /* Avoid "Unused parameter" warning */
+ extra = extra;
+
+ /* Verify validity of string */
+ if(len >= sizeof(ifnode->prevname))
+ {
+ fprintf(stderr, "Old Interface Name too long at line %d\n", linenum);
+ return(-1);
+ }
+
+ /* Copy */
+ memcpy(ifnode->prevname, string, len + 1);
+
+ /* Activate */
+ ifnode->active[SELECT_PREVNAME] = 1;
+ active[SELECT_PREVNAME] = 1;
+
+ if(verbose)
+ fprintf(stderr,
+ "Parsing : Added Old Interface Name `%s' from line %d.\n",
+ ifnode->prevname, linenum);
+
+ return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Compare the Previous Interface Name of two mappings
+ * Note : this one is special.
+ */
+static int
+mapping_cmpprevname(struct if_mapping * ifnode,
+ struct if_mapping * target)
+{
+ /* Do wildcard matching, case insensitive */
+ return(fnmatch(ifnode->prevname, target->ifname, FNM_CASEFOLD));
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Extract the Previous Interface Name from a live interface
+ */
+static int
+mapping_getprevname(int skfd,
+ const char * ifname,
+ struct if_mapping * target,
+ int flag)
+{
+ /* Avoid "Unused parameter" warning */
+ skfd = skfd; ifname = ifname; flag = flag;
+
+ /* Don't do anything, it's already in target->ifname ;-) */
+
+ /* Activate */
+ target->active[SELECT_PREVNAME] = 1;
+
+ return(0);
+}
+
/*********************** MAPPING MANAGEMENTS ***********************/
/*
struct if_mapping * ifnode;
char * star;
- /* Check overflow. */
- if(len > IFNAMSIZ)
+ star = memchr(pos, '*', len);
+
+ /* Check overflow, need one extra char for wildcard */
+ if((len + (star != NULL)) > IFNAMSIZ)
{
fprintf(stderr, "Error: Interface name `%.*s' too long at line %d\n",
(int) len, pos, linenum);
fprintf(stderr, "Warning: Alias device `%s' at line %d probably can't be mapped.\n",
ifnode->ifname, linenum);
- /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
- * This require specific kernel support (2.6.2-rc1 and later).
- * We externally use '*', but the kernel doesn't know about that,
- * so convert it to something it knows about... */
- star = strchr(ifnode->ifname, '*');
- if(star != NULL)
- {
- /* We need an extra char */
- if(len >= IFNAMSIZ)
- {
- fprintf(stderr,
- "Error: Interface wildcard `%s' too long at line %d\n",
- ifnode->ifname, linenum);
- free(ifnode);
- return(NULL);
- }
-
- /* Replace '*' with '%d' */
- memmove(star + 2, star + 1, len + 1 - (star - ifnode->ifname));
- star[0] = '%';
- star[1] = 'd';
- }
-
if(verbose)
fprintf(stderr, "Parsing : Added Mapping `%s' from line %d.\n",
ifnode->ifname, linenum);
* Probe interfaces based on our list of mappings.
* This is the default, but usually not the best way to do it.
*/
-static void
+static inline void
probe_mappings(int skfd)
{
struct if_mapping * ifnode;
for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next)
{
/* Can't load wildcards interface name :-( */
- if(strchr(ifnode->ifname, '%') != NULL)
+ if(strchr(ifnode->ifname, '*') != NULL)
continue;
if(verbose)
- fprintf(stderr, "Probing : Trying to load interface [%s]\n",
+ fprintf(stderr, "Probing : Trying to load/probe interface [%s]\n",
ifnode->ifname);
/* Trick the kernel into loading the interface.
* all built-in interfaces that should remain unconfigured won't
* be probed (and can have mappings).
*/
-static void
+static inline void
probe_debian(int skfd)
{
FILE * stream;
static int
process_rename(int skfd,
char * ifname,
- char * pattern)
+ char * newname)
{
- char newname[IFNAMSIZ+1];
char retname[IFNAMSIZ+1];
int len;
char * star;
- len = strlen(pattern);
- star = strchr(pattern, '*');
+ len = strlen(newname);
+ star = strchr(newname, '*');
/* Check newname length, need one extra char for wildcard */
if((len + (star != NULL)) > IFNAMSIZ)
{
fprintf(stderr, "Error: Interface name `%s' too long.\n",
- pattern);
+ newname);
return(-1);
}
- /* Copy to local buffer */
- memcpy(newname, pattern, len + 1);
-
- /* Convert wildcard to the proper format */
- if(star != NULL)
- {
- /* Replace '*' with '%d' in the new buffer */
- star += newname - pattern;
- memmove(star + 2, star + 1, len + 1 - (star - newname));
- star[0] = '%';
- star[1] = 'd';
- }
-
/* Change the name of the interface */
if(if_set_name(skfd, ifname, newname, retname) < 0)
{
if(target == NULL)
return(-1);
+ /* If udev is calling us, get the real devpath. */
+ if(udev_output)
+ {
+ const char *env;
+ /* It's passed to us as an environment variable */
+ env = getenv("DEVPATH");
+ if(env)
+ {
+ int env_len = strlen(env);
+ target->sysfs_devplen = env_len;
+ /* Make enough space for new interface name */
+ target->sysfs_devpath = malloc(env_len + IFNAMSIZ + 1);
+ if(target->sysfs_devpath != NULL)
+ memcpy(target->sysfs_devpath, env, env_len + 1);
+ }
+ /* We will get a second chance is the user has some sysfs selectors */
+ }
+
/* Find matching mapping */
mapping = mapping_find(target);
if(mapping == NULL)
* That would be tricky to do... */
if(dry_run)
{
- printf("Dry-run : Would rename %s to %s.\n",
- target->ifname, mapping->ifname);
- return(0);
+ strcpy(retname, mapping->ifname);
+ fprintf(stderr, "Dry-run : Would rename %s to %s.\n",
+ target->ifname, mapping->ifname);
}
-
- /* Change the name of the interface */
- if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
+ else
{
- fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
- target->ifname, mapping->ifname, strerror(errno));
- return(-1);
+ /* Change the name of the interface */
+ if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
+ {
+ fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
+ target->ifname, mapping->ifname, strerror(errno));
+ return(-1);
+ }
}
+ /* This one matched */
+ num_mapping_match++;
+
/* Check if called with an explicit interface name */
if(print_newname)
{
- /* Always print out the *new* interface name so that
- * the calling script can pick it up and know where its interface
- * has gone. */
- printf("%s\n", retname);
+ if(!udev_output)
+ /* Always print out the *new* interface name so that
+ * the calling script can pick it up and know where its interface
+ * has gone. */
+ printf("%s\n", retname);
+ else
+ /* udev likes to call us as an IMPORT action. This means that
+ * we need to return udev the environment variables changed.
+ * Obviously, we don't want to return anything is nothing changed. */
+ if(strcmp(target->ifname, retname))
+ {
+ char * pos;
+ /* Hack */
+ if(!target->sysfs_devpath)
+ mapping_getsysfs(skfd, ifname, target, 0);
+ /* Update devpath. Size is large enough. */
+ pos = strrchr(target->sysfs_devpath, '/');
+ if((pos != NULL) && (!strcmp(target->ifname, pos + 1)))
+ strcpy(pos + 1, retname);
+ /* Return new environment variables */
+ printf("DEVPATH=%s\nINTERFACE=%s\nINTERFACE_OLD=%s\n",
+ target->sysfs_devpath, retname, target->ifname);
+ }
}
/* Done */
/*
* Process all network interface present on the system.
*/
-static inline int
+static int
process_iflist(int skfd,
char * args[],
- int count)
+ int count,
+ int use_probe,
+ int is_debian)
{
num_takeover = 0;
+ num_mapping_match = 0;
+
+ /* Load all the necesary modules */
+ if(use_probe)
+ {
+ if(is_debian)
+ probe_debian(skfd);
+ else
+ probe_mappings(skfd);
+ }
/* Just do it */
iw_enum_devices(skfd, &process_ifname, args, count);
- /* If we do any takeover, the interface list grabbed with
- * iw_enum_devices() may get out of sync with the real interfaces,
- * and we may miss the victim interface. So, let's go through the
- * list again.
- * On the other hand, we may have ping pong between two interfaces,
- * each claiming the same name, so let's not do it forever...
- * Two time should be enough for most configs...
- * Jean II */
- if(force_takeover && num_takeover)
- /* Play it again, Sam... */
- iw_enum_devices(skfd, &process_ifname, args, count);
-
/* Done */
return(0);
}
{
const char * conf_file = DEFAULT_CONF;
char * ifname = NULL;
- int use_probe = 0;
- int is_debian = 0;
+ int use_probe = 0; /* Probe for modules */
+ int is_debian = 0; /* Debian quirks (probing) */
+ int print_num_match = 0; /* Print/Return num of matches */
int skfd;
int ret;
/* Loop over all command line options */
while(1)
{
- int c = getopt_long(argc, argv, "c:dDi:n:ptvV", long_opt, NULL);
+ int c = getopt_long(argc, argv, "c:CdDi:n:ptuvV", long_opt, NULL);
if(c == -1)
break;
case 'c':
conf_file = optarg;
break;
+ case 'C':
+ print_num_match = 1;
+ break;
case 'd':
is_debian = 1;
break;
case 't':
force_takeover = 1;
break;
+ case 'u':
+ udev_output = 1;
+ break;
case 'v':
printf("%-8.16s Wireless-Tools version %d\n", "ifrename", WT_VERSION);
return(0);
}
}
- /* Read the specified/default config file, or stdin. */
- if(mapping_readfile(conf_file) < 0)
- return(-1);
-
/* Create a channel to the NET kernel. */
if((skfd = iw_sockets_open()) < 0)
{
}
else
{
+ /* Read the specified/default config file, or stdin. */
+ if(mapping_readfile(conf_file) < 0)
+ return(-1);
+
/* Rename only this interface based on mappings
- * Mostly used for HotPlug processing (from /etc/hotplug/net.agent).
+ * Mostly used for HotPlug processing (from /etc/hotplug/net.agent)
+ * or udev processing (from a udev IMPORT rule).
* Process the network interface specified on the command line,
* and return the new name on stdout.
*/
}
else
{
- /* Load all the necesary modules */
- if(use_probe)
- {
- if(is_debian)
- probe_debian(skfd);
- else
- probe_mappings(skfd);
- }
+ /* Read the specified/default config file, or stdin. */
+ if(mapping_readfile(conf_file) < 0)
+ return(-1);
/* Rename all system interfaces
* Mostly used for boot time processing (from init scripts).
*/
- ret = process_iflist(skfd, NULL, 0);
+ ret = process_iflist(skfd, NULL, 0, use_probe, is_debian);
+
+ /* If we do any takeover, the interface list grabbed with
+ * iw_enum_devices() may get out of sync with the real interfaces,
+ * and we may miss the victim interface. So, let's go through the
+ * list again.
+ * On the other hand, we may have ping pong between two interfaces,
+ * each claiming the same name, so let's not do it forever...
+ * Two time should be enough for most configs...
+ * Note also that takeover is usually done with eth0, and many time
+ * we fail to probe eth0 because an unrenamed interface was using it,
+ * so we redo everything also when probing...
+ * Jean II */
+ if(force_takeover && (num_takeover || use_probe))
+ {
+ /* Play it again, Sam... */
+ ret = process_iflist(skfd, NULL, 0, use_probe, is_debian);
+ }
+
+ /* Print number of mapping that matched */
+ if(print_num_match)
+ {
+ fprintf(stderr, "Setting : %d mapping matched.\n", num_mapping_match);
+ ret = num_mapping_match;
+ }
}
/* Cleanup */