📄 ifrename.c
字号:
/* * Wireless Tools * * Jean II - HPL 04 * * 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> *//* * The changelog for ifrename is in the file CHANGELOG.h ;-) * * This work is a nearly complete rewrite of 'nameif.c'. * Original CopyRight of version of 'nameif' I used is : * ------------------------------------------------------- * Name Interfaces based on MAC address. * Writen 2000 by Andi Kleen. * Subject to the Gnu Public License, version 2. * TODO: make it support token ring etc. * $Id: nameif.c,v 1.3 2003/03/06 23:26:52 ecki Exp $ * ------------------------------------------------------- * * It started with a series of patches to nameif which never made * into the regular version, and had some architecural 'issues' with * those patches, which is the reason of this rewrite. * 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 hotplug invocation support. * o module loading support. * o MAC address wildcard. * o Interface name wildcard ('eth*' or 'wlan*'). * o Non-Ethernet MAC addresses (any size, not just 48 bits) *//***************************** INCLUDES *****************************//* This is needed to enable GNU extensions such as getline & FNM_CASEFOLD */#ifndef _GNU_SOURCE #define _GNU_SOURCE#endif#include <getopt.h> /* getopt_long() */#include <linux/sockios.h> /* SIOCSIFNAME */#include <fnmatch.h> /* fnmatch() *///#include <sys/syslog.h>#include "iwlib.h" /* Wireless Tools library */// This would be cool, unfortunately...//#include <linux/ethtool.h> /* Ethtool stuff -> struct ethtool_drvinfo *//************************ CONSTANTS & MACROS ************************//* Our default configuration file */const char DEFAULT_CONF[] = "/etc/iftab"; /* Debian stuff */const char DEBIAN_CONFIG_FILE[] = "/etc/network/interfaces";/* Backward compatibility */#ifndef ifr_newname#define ifr_newname ifr_ifru.ifru_slave#endif/* Types of selector we support. Must match selector_list */const int SELECT_MAC = 0; /* Select by MAC address */const int SELECT_ETHADDR = 1; /* Select by MAC address */const int SELECT_ARP = 2; /* Select by ARP type */const int SELECT_LINKTYPE = 3; /* Select by ARP type */const int SELECT_DRIVER = 4; /* Select by Driver name */const int SELECT_BUSINFO = 5; /* Select by Bus-Info */const int SELECT_FIRMWARE = 6; /* Select by Firmware revision */const int SELECT_BASEADDR = 7; /* Select by HW Base Address */const int SELECT_IRQ = 8; /* Select by HW Irq line */const int SELECT_INTERRUPT = 9; /* Select by HW Irq line */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#define HAS_MAC_EXACT 1#define HAS_MAC_FILTER 2#define MAX_MAC_LEN 16 /* Maximum lenght of MAC address */const struct ether_addr zero_mac = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};const struct option long_opt[] ={ {"config-file", 1, NULL, 'c' }, {"debian", 0, NULL, 'd' }, {"dry-run", 0, NULL, 'D' }, {"help", 0, NULL, '?' }, {"interface", 1, NULL, 'i' }, {"newname", 1, NULL, 'n' }, {"takeover", 0, NULL, 't' }, {"version", 0, NULL, 'v' }, {"verbose", 0, NULL, 'V' }, {NULL, 0, NULL, '\0' },};/* Pcmcia stab files */#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/* Userspace headers lag, fix that... */#ifndef ARPHRD_IEEE1394#define ARPHRD_IEEE1394 24#endif#ifndef ARPHRD_EUI64#define ARPHRD_EUI64 27#endif#ifndef ARPHRD_IRDA#define ARPHRD_IRDA 783#endif/* Length of various non-standard MAC addresses */const int weird_mac_len[][2] ={ { ARPHRD_IEEE1394, 8 }, { ARPHRD_EUI64, 8 }, { ARPHRD_IRDA, 4 },};const int weird_mac_len_num = sizeof(weird_mac_len) / sizeof(weird_mac_len[0]);/****************************** TYPES ******************************//* Cut'n'paste from ethtool.h */#define ETHTOOL_BUSINFO_LEN 32/* these strings are set to whatever the driver author decides... */struct ethtool_drvinfo { __u32 cmd; char driver[32]; /* driver short name, "tulip", "eepro100" */ char version[32]; /* driver version string */ char fw_version[32]; /* firmware version string, if applicable */ char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ /* For PCI devices, use pci_dev->slot_name. */ char reserved1[32]; char reserved2[16]; __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ __u32 testinfo_len; __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */};#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. *//* Description of an interface mapping */typedef struct if_mapping{ /* Linked list */ struct if_mapping * next; /* Name of this interface */ char ifname[IFNAMSIZ+1]; /* Selectors for this interface */ int active[SELECT_NUM]; /* Selectors active */ /* Selector data */ unsigned char mac[MAX_MAC_LEN]; /* Exact MAC address, hex */ int mac_len; /* Length (usually 6) */ char mac_filter[16*3 + 1]; /* WildCard, ascii */ unsigned short hw_type; /* Link/ARP type */ char driver[32]; /* driver short name */ char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ char fw_version[32]; /* Firmware revision */ unsigned short base_addr; /* HW Base I/O address */ unsigned char irq; /* HW irq line */ char iwproto[IFNAMSIZ + 1]; /* Wireless/protocol name */ int pcmcia_slot; /* Pcmcia slot */ char * sysfs[SYSFS_MAX_FILE]; /* sysfs selectors */} if_mapping;/* Extra parsing information when adding a mapping */typedef struct add_extra{ char * modif_pos; /* Descriptor modifier */ size_t modif_len;} parsing_extra;/* Prototype for adding a selector to a mapping. Return -1 if invalid value. */typedef int (*mapping_add)(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);/* Prototype for comparing the selector of two mapping. Return 0 if matches. */typedef int (*mapping_cmp)(struct if_mapping * ifnode, struct if_mapping * target);/* Prototype for extracting selector value from live interface */typedef int (*mapping_get)(int skfd, const char * ifname, struct if_mapping * target, int flag);/* How to handle a selector */typedef struct mapping_selector{ char * name; mapping_add add_fn; mapping_cmp cmp_fn; mapping_get get_fn;} mapping_selector;/* sysfs global data */typedef struct sysfs_metadata{ char * root; /* Root of the sysfs */ int rlen; /* Size of it */ int filenum; /* Number of files */ char * filename[SYSFS_MAX_FILE]; /* Name of files */} sysfs_metadata;/**************************** PROTOTYPES ****************************/static int mapping_addmac(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmpmac(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_getmac(int skfd, const char * ifname, struct if_mapping * target, int flag);static int mapping_addarp(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmparp(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_getarp(int skfd, const char * ifname, struct if_mapping * target, int flag);static int mapping_adddriver(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmpdriver(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_addbusinfo(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmpbusinfo(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_addfirmware(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmpfirmware(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_getdriverbusinfo(int skfd, const char * ifname, struct if_mapping * target, int flag);static int mapping_addbaseaddr(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmpbaseaddr(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_addirq(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmpirq(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_getbaseaddrirq(int skfd, const char * ifname, struct if_mapping * target, int flag);static int mapping_addiwproto(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmpiwproto(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_getiwproto(int skfd, const char * ifname, struct if_mapping * target, int flag);static int mapping_addpcmciaslot(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmppcmciaslot(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_getpcmciaslot(int skfd, const char * ifname, struct if_mapping * target, int flag);static int mapping_addsysfs(struct if_mapping * ifnode, int * active, char * pos, size_t len, struct add_extra * extra, int linenum);static int mapping_cmpsysfs(struct if_mapping * ifnode, struct if_mapping * target);static int mapping_getsysfs(int skfd, const char * ifname, struct if_mapping * target, int flag);/**************************** VARIABLES ****************************//* List of mapping read for config file */struct if_mapping * mapping_list = NULL;/* List of selectors we can handle */const struct mapping_selector selector_list[] ={ /* MAC address and ARP/Link type from ifconfig */ { "mac", &mapping_addmac, &mapping_cmpmac, &mapping_getmac }, { "ethaddr", &mapping_addmac, &mapping_cmpmac, &mapping_getmac }, { "arp", &mapping_addarp, &mapping_cmparp, &mapping_getarp }, { "linktype", &mapping_addarp, &mapping_cmparp, &mapping_getarp }, /* Driver name, Bus-Info and firmware rev from ethtool -i */ { "driver", &mapping_adddriver, &mapping_cmpdriver, &mapping_getdriverbusinfo }, { "businfo", &mapping_addbusinfo, &mapping_cmpbusinfo, &mapping_getdriverbusinfo }, { "firmware", &mapping_addfirmware, &mapping_cmpfirmware, &mapping_getdriverbusinfo }, /* Base Address and IRQ from ifconfig */ { "baseaddress", &mapping_addbaseaddr, &mapping_cmpbaseaddr, &mapping_getbaseaddrirq }, { "irq", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq }, { "interrupt", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq }, /* Wireless Protocol from iwconfig */ { "iwproto", &mapping_addiwproto, &mapping_cmpiwproto, &mapping_getiwproto }, /* Pcmcia slot from cardmgr */ { "pcmciaslot", &mapping_addpcmciaslot, &mapping_cmppcmciaslot, &mapping_getpcmciaslot }, /* sysfs file (udev emulation) */ { "sysfs", &mapping_addsysfs, &mapping_cmpsysfs, &mapping_getsysfs }, /* The Terminator */ { NULL, NULL, NULL, NULL },};const int selector_num = sizeof(selector_list)/sizeof(selector_list[0]);/* List of active selectors */int selector_active[SELECT_NUM]; /* Selectors active *//* * All the following flags are controlled by the command line switches... * It's a bit hackish to have them all as global, so maybe we should pass * them in a big struct as function arguments... More complex and * probably not worth it ? *//* Invocation type */int print_newname = 0;char * new_name = NULL;/* Takeover support */int force_takeover = 0; /* Takeover name from other interface */int num_takeover = 0; /* Number of takeover done *//* Dry-run support */int dry_run = 0; /* Just print new name, don't rename *//* Verbose support (i.e. debugging) */int verbose = 0;/* sysfs global data */struct sysfs_metadata sysfs_global ={ NULL, 0, 0, { NULL, NULL, NULL, NULL, NULL },};/******************** INTERFACE NAME MANAGEMENT ********************//* * Bunch of low level function for managing interface names. *//*------------------------------------------------------------------*//* * Compare two interface names, with wildcards. * We can't use fnmatch() because we don't want expansion of '[...]' * expressions, '\' sequences and matching of '.'. * We only want to match a single '*' (converted to a %d at that point) * to a numerical value (no ascii). * Return 0 is matches. */static intif_match_ifname(const char * pattern, const char * value){ const char * p; const char * v; int n; int ret; /* Check for a wildcard (converted from '*' to '%d' in mapping_create()) */ p = strstr(pattern, "%d"); /* No wildcard, simple comparison */ if(p == NULL) return(strcmp(pattern, value)); /* Check is prefixes match */ n = (p - pattern); ret = strncmp(pattern, value, n); if(ret) return(ret); /* Check that value has some digits at this point */ v = value + n; if(!isdigit(*v)) return(-1); /* Skip digits to go to value suffix */ do v++; while(isdigit(*v)); /* Pattern suffix */ p += 2; /* Compare suffixes */ return(strcmp(p, v));}/*------------------------------------------------------------------*//* * Steal interface name from another interface. This enable interface * name swapping. * This will work : * 1) with kernel 2.6.X * 2) if other interface is down * Because of (2), it won't work with hotplug, but we don't need it * with hotplug, only with static ifaces... */static intif_takeover_name(int skfd, const char * victimname){ char autoname[IFNAMSIZ+1]; int len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -