aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Hoyer <harald@redhat.com>2010-07-15 13:59:24 +0200
committerHarald Hoyer <harald@redhat.com>2010-07-15 14:11:47 +0200
commitec5d526e4c33b911a374c60127d7767ea20c66e0 (patch)
treea4595fe5133b3c20de01d2f51e2476922fb0798f
parent06fc83db4e0e693d64ea0fa0b58c935863908d8b (diff)
downloadinitscripts-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.c180
-rw-r--r--udev/rules.d/60-net.rules9
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"