diff options
author | Harald Hoyer <harald@redhat.com> | 2010-07-15 13:59:24 +0200 |
---|---|---|
committer | Harald Hoyer <harald@redhat.com> | 2010-07-15 14:11:47 +0200 |
commit | ec5d526e4c33b911a374c60127d7767ea20c66e0 (patch) | |
tree | a4595fe5133b3c20de01d2f51e2476922fb0798f | |
parent | 06fc83db4e0e693d64ea0fa0b58c935863908d8b (diff) | |
download | initscripts-ec5d526e4c33b911a374c60127d7767ea20c66e0.tar initscripts-ec5d526e4c33b911a374c60127d7767ea20c66e0.tar.gz initscripts-ec5d526e4c33b911a374c60127d7767ea20c66e0.tar.bz2 initscripts-ec5d526e4c33b911a374c60127d7767ea20c66e0.tar.xz initscripts-ec5d526e4c33b911a374c60127d7767ea20c66e0.zip |
rename_device: try to find free slots and reorder for configured devices
-rw-r--r-- | src/rename_device.c | 180 | ||||
-rw-r--r-- | udev/rules.d/60-net.rules | 9 |
2 files changed, 186 insertions, 3 deletions
diff --git a/src/rename_device.c b/src/rename_device.c index 197fbdb3..07be39cc 100644 --- a/src/rename_device.c +++ b/src/rename_device.c @@ -229,6 +229,89 @@ char *get_config_by_hwaddr(char *hwaddr, char *current) { return first; } +struct netdev *get_config_by_name(char *name) { + struct netdev *config; + + if (!name) return NULL; + + for (config = configs; config; config = config->next) { + if (strcasecmp(config->dev, name) == 0) + return config; + } + return NULL; +} + +int check_persistent_by_name(char *name) { + FILE *fptr; + int ret = 1; + char *scanstr=NULL; + + asprintf(&scanstr, "NAME=\"%s\"", name); + if (scanstr == NULL) + return 1; + + fptr = fopen("/etc/udev/rules.d/70-persistent-net.rules", "r"); + if (fptr == NULL) + return 1; + + while(!feof(fptr)) { + char line[4096]; + line[0]=0; + if (fgets(line, sizeof(line), fptr) == NULL) + break; + + /* ignore lines hinted from us */ + if (strstr(line, "INTERFACE_NAME")) + continue; + + if (strstr(line, scanstr)) { + ret = 0; + break; + } + } + + fclose(fptr); + return ret; +} + +char *get_persistent_by_hwaddr(char *hw) { + FILE *fptr; + char *scanstr=NULL; + char target[256]; + + target[0]=0; + + asprintf(&scanstr, "ATTR{address}==\"%s\"", hw); + if (scanstr == NULL) + return NULL; + + fptr = fopen("/etc/udev/rules.d/70-persistent-net.rules", "r"); + if (fptr == NULL) + return NULL; + + while(!feof(fptr)) { + char line[4096]; + line[0]=0; + if (fgets(line, sizeof(line), fptr) == NULL) + break; + + if (strstr(line, scanstr)) { + char *cptr; +#define NAME_STR "NAME=\"" + cptr = strstr(line, NAME_STR); + if (cptr == NULL) + continue; + if(sscanf(cptr+sizeof(NAME_STR)-1, "%255[^\"]\"", target) == 1) { + fclose(fptr); + return strdup(target); + } + } + } + + fclose(fptr); + return NULL; +} + void take_lock() { int count = 0; int lockfd; @@ -264,9 +347,67 @@ void take_lock() { return; } +int check_and_set_claimed(char *src, char *name) +{ + int fd; + char *fname; + if (src == NULL || name == NULL) + return 1; + + asprintf(&fname, "/dev/.udev/.%s.claimed", name); + fd = open(fname, O_CREAT|O_EXCL|O_WRONLY, 0600); + if (fd < 0 ) + return 1; + + write(fd, src, strlen(src)); + close(fd); + return 0; +} + +char *get_next_free(char *name) +{ + char *target=NULL; + int num; + char inamebase[256]; + char inamesuffix[256]; + struct netdev *config; + + inamebase[0]=0; + inamesuffix[0]=0; + if (sscanf(name, "%[^0-9]%d%s", inamebase, &num, inamesuffix) < 2) + return NULL; + + num = -1; + + /* we need to stop at some point */ + while(num < 32000) { + num++; + + if (target) + free(target); + + asprintf(&target, "%s%d%s", inamebase, num, inamesuffix); + + config = get_config_by_name(target); + if (config && config->hwaddr) + continue; + + /* Parse /etc/udev/rules.d/70-persistent-net.rules. */ + if (check_persistent_by_name(target) == 0) + continue; + + if (check_and_set_claimed(name, target) != 0) + continue; + + return target; + } + return name; +} + int main(int argc, char **argv) { char *src, *target, *hw; struct timeval tv; + struct netdev *config; gettimeofday(&tv, NULL); srand(tv.tv_usec); @@ -289,10 +430,45 @@ int main(int argc, char **argv) { if (!hw) goto out_unlock; target = get_config_by_hwaddr(hw, src); - if (!target) + + if (target) { + printf("INTERFACE_NAME=%s", target); goto out_unlock; + } - printf("%s", target); +#if !defined(__s390__) && !defined(__s390x__) + + /* There is a hw, but no corresponding interface. + Now, check if there is a ifcfg file, which claims + the interface name + */ + config = get_config_by_name(src); + if ((config == NULL) || (config->hwaddr == NULL)) { + /* found no config or the config has no HWADDR */ + if (check_and_set_claimed(src, src) == 0) + goto out_unlock; + } + + /* Interface name is taken already, now try to find + a free slot. + */ + /* Parse /etc/udev/rules.d/70-persistent-net.rules. */ + target = get_persistent_by_hwaddr(hw); + + if (target) { + /* Check if persistent-net.rules interface is taken in ifcfg. */ + config = get_config_by_name(target); + if ((config == NULL) || (config->hwaddr == NULL)) { + if (check_and_set_claimed(src, target) == 0) + goto out_unlock; + } + } + + /* Find a free name slot */ + target = get_next_free(src); + if (target) + printf("INTERFACE_NAME=%s", target); +#endif out_unlock: unlink(LOCKFILE); diff --git a/udev/rules.d/60-net.rules b/udev/rules.d/60-net.rules index 5a2146d9..70fc3b54 100644 --- a/udev/rules.d/60-net.rules +++ b/udev/rules.d/60-net.rules @@ -1,3 +1,10 @@ ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/virtual/net/lo", RUN+="/sbin/ifup $env{INTERFACE}" -ACTION=="add", SUBSYSTEM=="net", PROGRAM="/lib/udev/rename_device", RESULT=="?*", ENV{INTERFACE_NAME}="$result" + +KERNEL!="eth*|ath*|wlan*[0-9]|msh*|ra*|sta*|ctc*|lcs*|hsi*", GOTO="net_end" + +ACTION=="add", SUBSYSTEM=="net", IMPORT="/lib/udev/rename_device" +ACTION=="remove", SUBSYSTEM=="net", RUN+="/bin/rm -f /dev/.udev/.$name.claimed" + SUBSYSTEM=="net", RUN+="/etc/sysconfig/network-scripts/net.hotplug" + +LABEL="net_end" |