📄 ifrename.c
字号:
linenum); else fprintf(stderr, "Error: Line %d ignored due to prior errors\n", linenum); free(ifnode); } else { /* Link it in the list */ ifnode->next = mapping_list; mapping_list = ifnode; } } /* Cleanup */ free(linebuf); /* Finished reading, close the file */ if(stream != stdin) fclose(stream); return(0);}/*------------------------------------------------------------------*//* * Extract all the interesting selectors for the interface in consideration */static struct if_mapping *mapping_extract(int skfd, const char * ifname){ struct if_mapping * target; int i; /* Create mapping, zero it */ target = calloc(1, sizeof(if_mapping)); if(!target) { fprintf(stderr, "Error: Can't allocate interface mapping.\n"); return(NULL); } /* Set the interface name */ strcpy(target->ifname, ifname); /* Loop on all active selectors */ for(i = 0; i < SELECT_NUM; i++) { /* Check if this selector is active */ if(selector_active[i] != 0) { /* Extract selector */ selector_list[i].get_fn(skfd, ifname, target, selector_active[i]); /* Ignore errors. Some mapping may not need all selectors */ } } return(target);} /*------------------------------------------------------------------*//* * Find the first mapping in the list matching the one we want. */static struct if_mapping *mapping_find(struct if_mapping * target){ struct if_mapping * ifnode; int i; /* Look over all our mappings */ for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next) { int matches = 1; /* Look over all our selectors, all must match */ for(i = 0; i < SELECT_NUM; i++) { /* Check if this selector is active */ if(ifnode->active[i] != 0) { /* If this selector doesn't match, game over for this mapping */ if((target->active[i] == 0) || (selector_list[i].cmp_fn(ifnode, target) != 0)) { matches = 0; break; } } } /* Check is this mapping was "the one" */ if(matches) return(ifnode); } /* Not found */ return(NULL);} /************************** MODULE SUPPORT **************************//* * Load all necessary module so that interfaces do exist. * This is necessary for system that are fully modular when * doing the boot time processing, because we need to run before * 'ifup -a'. *//*------------------------------------------------------------------*//* * Probe interfaces based on our list of mappings. * This is the default, but usually not the best way to do it. */static voidprobe_mappings(int skfd){ struct if_mapping * ifnode; struct ifreq ifr; /* Look over all our mappings */ for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next) { /* Can't load wildcards interface name :-( */ if(strchr(ifnode->ifname, '%') != NULL) continue; if(verbose) fprintf(stderr, "Probing : Trying to load interface [%s]\n", ifnode->ifname); /* Trick the kernel into loading the interface. * This allow us to not depend on the exact path and * name of the '/sbin/modprobe' command. * Obviously, we expect this command to 'fail', as * the interface will load with the old/wrong name. */ strncpy(ifr.ifr_name, ifnode->ifname, IFNAMSIZ); ioctl(skfd, SIOCGIFHWADDR, &ifr); }}/*------------------------------------------------------------------*//* * Probe interfaces based on Debian's config files. * This allow to enly load modules for interfaces the user want active, * all built-in interfaces that should remain unconfigured won't * be probed (and can have mappings). */static voidprobe_debian(int skfd){ FILE * stream; char * linebuf = NULL; size_t linelen = 0; struct ifreq ifr; /* Open Debian config file */ stream = fopen(DEBIAN_CONFIG_FILE, "r"); if(stream == NULL) { fprintf(stderr, "Error: can't open file [%s]\n", DEBIAN_CONFIG_FILE); return; } /* 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) { char * p; char * e; size_t n; /* Check for auto keyword, ignore when commented out */ if(!strncasecmp(linebuf, "auto ", 5)) { /* Skip "auto" keyword */ p = linebuf + 5; /* Terminate at first comment */ e = strchr(p, '#'); if(e != NULL) *e = '\0'; /* Loop on all interfaces given */ while(*p != '\0') { /* Interface name length */ n = strcspn(p, " \t\n"); /* Look for end of interface name */ e = p + n; /* Make 'e' point past the '\0' we are going to add */ if(*e != '\0') e++; /* Terminate interface name */ p[n] = '\0'; if(verbose) fprintf(stderr, "Probing : Trying to load interface [%s]\n", p); /* Load interface */ strncpy(ifr.ifr_name, p, IFNAMSIZ); ioctl(skfd, SIOCGIFHWADDR, &ifr); /* Go to next interface name */ p = e; p += strspn(p, " \t\n"); } } } /* Done */ fclose(stream); return;}/**************************** MAIN LOGIC ****************************//*------------------------------------------------------------------*//* * Rename an interface to a specified new name. */static intprocess_rename(int skfd, char * ifname, char * pattern){ char newname[IFNAMSIZ+1]; char retname[IFNAMSIZ+1]; int len; char * star; len = strlen(pattern); star = strchr(pattern, '*'); /* Check newname length, need one extra char for wildcard */ if((len + (star != NULL)) > IFNAMSIZ) { fprintf(stderr, "Error: Interface name `%s' too long.\n", pattern); 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) { fprintf(stderr, "Error: cannot change name of %s to %s: %s\n", ifname, newname, strerror(errno)); return(-1); } /* 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); /* Done */ return(0);}/*------------------------------------------------------------------*//* * Process a specified interface. */static intprocess_ifname(int skfd, char * ifname, char * args[], int count){ struct if_mapping * target; const struct if_mapping * mapping; char retname[IFNAMSIZ+1]; /* Avoid "Unused parameter" warning */ args = args; count = count; /* Get description of this interface */ target = mapping_extract(skfd, ifname); if(target == NULL) return(-1); /* Find matching mapping */ mapping = mapping_find(target); if(mapping == NULL) return(-1); /* If user specified a new name, keep only interfaces that would * match the new name... */ if((new_name != NULL) && (if_match_ifname(mapping->ifname, new_name) != 0)) return(-1); /* Check if user want only dry-run. * Note that, in the case of wildcard, we don't resolve the wildcard. * That would be tricky to do... */ if(dry_run) { printf("Dry-run : Would rename %s to %s.\n", target->ifname, mapping->ifname); return(0); } /* 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); } /* 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); } /* Done */ return(0);}/*------------------------------------------------------------------*//* * Process all network interface present on the system. */static inline intprocess_iflist(int skfd, char * args[], int count){ num_takeover = 0; /* 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);}/******************************* MAIN *******************************//*------------------------------------------------------------------*//* */static voidusage(void){ fprintf(stderr, "usage: ifrename [-c configurationfile] [-i ifname] [-p] [-t] [-d] [-D]\n"); exit(1); }/*------------------------------------------------------------------*//* * The main ! */intmain(int argc, char * argv[]) { const char * conf_file = DEFAULT_CONF; char * ifname = NULL; int use_probe = 0; int is_debian = 0; 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); if(c == -1) break; switch(c) { default: case '?': usage(); case 'c': conf_file = optarg; break; case 'd': is_debian = 1; break; case 'D': dry_run = 1; break; case 'i': ifname = optarg; break; case 'n': new_name = optarg; break; case 'p': use_probe = 1; break; case 't': force_takeover = 1; break; case 'v': printf("%-8.16s Wireless-Tools version %d\n", "ifrename", WT_VERSION); return(0); case 'V': verbose = 1; break; } } /* 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) { perror("socket"); return(-1); } /* Check if interface name was specified with -i. */ if(ifname != NULL) { /* Check is target name specified */ if(new_name != NULL) { /* User want to simply rename an interface to a specified name */ ret = process_rename(skfd, ifname, new_name); } else { /* Rename only this interface based on mappings * Mostly used for HotPlug processing (from /etc/hotplug/net.agent). * Process the network interface specified on the command line, * and return the new name on stdout. */ print_newname = 1; ret = process_ifname(skfd, ifname, NULL, 0); } } else { /* Load all the necesary modules */ if(use_probe) { if(is_debian) probe_debian(skfd); else probe_mappings(skfd); } /* Rename all system interfaces * Mostly used for boot time processing (from init scripts). */ ret = process_iflist(skfd, NULL, 0); } /* Cleanup */ iw_sockets_close(skfd); return(ret);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -