📄 ifrename.c
字号:
/* Search if the filename already exist */ for(findex = 0; findex < sysfs_global.filenum; findex++) { if(!strcmp(extra->modif_pos, sysfs_global.filename[findex])) break; } /* If filename does not exist, creates it */ if(findex == sysfs_global.filenum) { if(findex == SYSFS_MAX_FILE) { fprintf(stderr, "Error: Too many SYSFS filenames at line %d\n", linenum); return(-1); } sdup = strndup(extra->modif_pos, extra->modif_len); if(sdup == NULL) { fprintf(stderr, "Error: Can't allocate SYSFS file\n"); return(-1); } sysfs_global.filename[findex] = sdup; sysfs_global.filenum++; } /* Store value */ sdup = strndup(string, len); if(sdup == NULL) { fprintf(stderr, "Error: Can't allocate SYSFS value\n"); return(-1); } ifnode->sysfs[findex] = sdup; /* Activate */ ifnode->active[SELECT_SYSFS] = 1; active[SELECT_SYSFS] = 1; if(verbose) fprintf(stderr, "Parsing : Added SYSFS filename `%s' value `%s' from line %d.\n", sysfs_global.filename[findex], ifnode->sysfs[findex], linenum); return(0);}/*------------------------------------------------------------------*//* * Compare all the sysfs values of two mappings */static intmapping_cmpsysfs(struct if_mapping * ifnode, struct if_mapping * target){ int findex; /* filename index */ int match = 1; /* Loop on all sysfs selector */ for(findex = 0; findex < sysfs_global.filenum; findex++) { /* If the mapping defines this sysfs selector.. */ if(ifnode->sysfs[findex] != NULL) /* And if the sysfs values don't match */ if((target->sysfs[findex] == NULL) || (fnmatch(ifnode->sysfs[findex], target->sysfs[findex], FNM_CASEFOLD))) /* Then the sysfs selector doesn't match */ match = 0; } return(!match);}/*------------------------------------------------------------------*//* * Extract all the sysfs values of an interface */static intmapping_getsysfs(int skfd, const char * ifname, struct if_mapping * target, int flag){ FILE * stream; char * fname; int fnsize; char * linebuf = NULL; size_t linelen = 0; char * sdup; int findex; /* filename index */ /* Avoid "Unused parameter" warning */ skfd = skfd; flag = flag; /* Check if we know the devpath of this device */ if(target->sysfs_devpath == NULL) { /* Check if we know the root of the sysfs filesystem */ if(sysfs_global.root == 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) { 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++) { while(isspace(*p)) ++p; token[i] = p; n = strcspn(p, " \t\n"); toklen[i] = n; p += n; } /* 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 */ } /* Cleanup */ fclose(stream); /* 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 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 * p; ssize_t n; /* Construct complete filename for the sysfs selector */ 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/%s", target->sysfs_devpath, sysfs_global.filename[findex]); /* Open the sysfs file for reading */ stream = fopen(fname, "r"); if(!stream) { /* Some sysfs attribute may no exist for some interface */ if(verbose) fprintf(stderr, "Error: Can't open file `%s': %s\n", fname, strerror(errno)); /* Next sysfs selector */ continue; } /* Read file. Only one line in file. */ n = getline(&linebuf, &linelen, stream); fclose(stream); if(n <= 0) { /* 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; /* 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"); free(linebuf); return(-1); } target->sysfs[findex] = sdup; /* Activate */ target->active[SELECT_SYSFS] = 1; if(verbose) fprintf(stderr, "Querying %s : Got SYSFS filename `%s' value `%s'.\n", ifname, sysfs_global.filename[findex], target->sysfs[findex]); /* Finished : Next sysfs selector */ } /* Cleanup */ free(linebuf); return(target->active[SELECT_SYSFS] ? 0 : -1);}/*------------------------------------------------------------------*//* * Add a Previous Interface Name selector to a mapping */static intmapping_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 intmapping_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 intmapping_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 ***********************//* * Manage interface mappings. * Each mapping tell us how to identify a specific interface name. * It is composed of a bunch of selector values. *//*------------------------------------------------------------------*//* * Create a new interface mapping and verify its name */static struct if_mapping *mapping_create(char * pos, int len, int linenum){ struct if_mapping * ifnode; char * star; 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); return(NULL); } /* Create mapping, zero it */ ifnode = calloc(1, sizeof(if_mapping)); if(!ifnode) { fprintf(stderr, "Error: Can't allocate interface mapping.\n"); return(NULL); } /* Set the name, terminates it */ memcpy(ifnode->ifname, pos, len); ifnode->ifname[len] = '\0'; /* Check the interface name and issue various pedantic warnings. * We assume people using takeover want to force interfaces to those * names and know what they are doing, so don't bother them... */ if((!force_takeover) && ((!strcmp(ifnode->ifname, "eth0")) || (!strcmp(ifnode->ifname, "wlan0")))) fprintf(stderr, "Warning: Interface name is `%s' at line %d, can't be mapped reliably.\n", ifnode->ifname, linenum); if(strchr(ifnode->ifname, ':')) fprintf(stderr, "Warning: Alias device `%s' at line %d probably can't be mapped.\n", ifnode->ifname, linenum); if(verbose) fprintf(stderr, "Parsing : Added Mapping `%s' from line %d.\n", ifnode->ifname, linenum); /* Done */ return(ifnode);}/*------------------------------------------------------------------*//* * Find the most appropriate selector matching a given selector name */static inline const struct mapping_selector *selector_find(const char * string, size_t slen, int linenum){ const struct mapping_selector * found = NULL; int ambig = 0; int i; /* Go through all selectors */ for(i = 0; selector_list[i].name != NULL; ++i) { /* No match -> next one */ if(strncasecmp(selector_list[i].name, string, slen) != 0) continue; /* Exact match -> perfect */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -