6 * Main code for "ifrename". This is tool allows to rename network
7 * interfaces based on various criteria (not only wireless).
8 * You need to link this code against "iwlib.c" and "-lm".
10 * This file is released under the GPL license.
11 * Copyright (c) 2004 Jean Tourrilhes <jt@hpl.hp.com>
15 * The changelog for ifrename is in the file CHANGELOG.h ;-)
17 * This work is a nearly complete rewrite of 'nameif.c'.
18 * Original CopyRight of version of 'nameif' I used is :
19 * -------------------------------------------------------
20 * Name Interfaces based on MAC address.
21 * Writen 2000 by Andi Kleen.
22 * Subject to the Gnu Public License, version 2.
23 * TODO: make it support token ring etc.
24 * $Id: nameif.c,v 1.3 2003/03/06 23:26:52 ecki Exp $
25 * -------------------------------------------------------
27 * It started with a series of patches to nameif which never made
28 * into the regular version, and had some architecural 'issues' with
29 * those patches, which is the reason of this rewrite.
30 * Difference with standard 'nameif' :
31 * o 'nameif' has only a single selector, the interface MAC address.
32 * o Modular selector architecture, easily add new selectors.
33 * o Wide range of selector, including sysfs...
34 * o hotplug invocation support.
35 * o module loading support.
36 * o MAC address wildcard.
37 * o Interface name wildcard ('eth*' or 'wlan*').
38 * o Non-Ethernet MAC addresses (any size, not just 48 bits)
41 /***************************** INCLUDES *****************************/
43 /* This is needed to enable GNU extensions such as getline & FNM_CASEFOLD */
48 #include <getopt.h> /* getopt_long() */
49 #include <linux/sockios.h> /* SIOCSIFNAME */
50 #include <fnmatch.h> /* fnmatch() */
51 //#include <sys/syslog.h>
53 #include "iwlib.h" /* Wireless Tools library */
55 // This would be cool, unfortunately...
56 //#include <linux/ethtool.h> /* Ethtool stuff -> struct ethtool_drvinfo */
58 /************************ CONSTANTS & MACROS ************************/
60 /* Our default configuration file */
61 const char DEFAULT_CONF[] = "/etc/iftab";
64 const char DEBIAN_CONFIG_FILE[] = "/etc/network/interfaces";
66 /* Backward compatibility */
68 #define ifr_newname ifr_ifru.ifru_slave
71 /* Types of selector we support. Must match selector_list */
72 const int SELECT_MAC = 0; /* Select by MAC address */
73 const int SELECT_ETHADDR = 1; /* Select by MAC address */
74 const int SELECT_ARP = 2; /* Select by ARP type */
75 const int SELECT_LINKTYPE = 3; /* Select by ARP type */
76 const int SELECT_DRIVER = 4; /* Select by Driver name */
77 const int SELECT_BUSINFO = 5; /* Select by Bus-Info */
78 const int SELECT_FIRMWARE = 6; /* Select by Firmware revision */
79 const int SELECT_BASEADDR = 7; /* Select by HW Base Address */
80 const int SELECT_IRQ = 8; /* Select by HW Irq line */
81 const int SELECT_INTERRUPT = 9; /* Select by HW Irq line */
82 const int SELECT_IWPROTO = 10; /* Select by Wireless Protocol */
83 const int SELECT_PCMCIASLOT = 11; /* Select by Pcmcia Slot */
84 const int SELECT_SYSFS = 12; /* Select by sysfs file */
87 #define HAS_MAC_EXACT 1
88 #define HAS_MAC_FILTER 2
89 #define MAX_MAC_LEN 16 /* Maximum lenght of MAC address */
91 const struct ether_addr zero_mac = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
93 const struct option long_opt[] =
95 {"config-file", 1, NULL, 'c' },
96 {"debian", 0, NULL, 'd' },
97 {"dry-run", 0, NULL, 'D' },
98 {"help", 0, NULL, '?' },
99 {"interface", 1, NULL, 'i' },
100 {"newname", 1, NULL, 'n' },
101 {"takeover", 0, NULL, 't' },
102 {"version", 0, NULL, 'v' },
103 {"verbose", 0, NULL, 'V' },
104 {NULL, 0, NULL, '\0' },
107 /* Pcmcia stab files */
108 #define PCMCIA_STAB1 "/var/lib/pcmcia/stab"
109 #define PCMCIA_STAB2 "/var/run/stab"
111 /* Max number of sysfs file we support */
112 #define SYSFS_MAX_FILE 5
114 /* Userspace headers lag, fix that... */
115 #ifndef ARPHRD_IEEE1394
116 #define ARPHRD_IEEE1394 24
119 #define ARPHRD_EUI64 27
122 #define ARPHRD_IRDA 783
125 /* Length of various non-standard MAC addresses */
126 const int weird_mac_len[][2] =
128 { ARPHRD_IEEE1394, 8 },
132 const int weird_mac_len_num = sizeof(weird_mac_len) / sizeof(weird_mac_len[0]);
134 /****************************** TYPES ******************************/
136 /* Cut'n'paste from ethtool.h */
137 #define ETHTOOL_BUSINFO_LEN 32
138 /* these strings are set to whatever the driver author decides... */
139 struct ethtool_drvinfo {
141 char driver[32]; /* driver short name, "tulip", "eepro100" */
142 char version[32]; /* driver version string */
143 char fw_version[32]; /* firmware version string, if applicable */
144 char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */
145 /* For PCI devices, use pci_dev->slot_name. */
148 __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */
150 __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */
151 __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */
153 #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */
155 /* Description of an interface mapping */
156 typedef struct if_mapping
159 struct if_mapping * next;
161 /* Name of this interface */
162 char ifname[IFNAMSIZ+1];
164 /* Selectors for this interface */
165 int active[SELECT_NUM]; /* Selectors active */
168 unsigned char mac[MAX_MAC_LEN]; /* Exact MAC address, hex */
169 int mac_len; /* Length (usually 6) */
170 char mac_filter[16*3 + 1]; /* WildCard, ascii */
171 unsigned short hw_type; /* Link/ARP type */
172 char driver[32]; /* driver short name */
173 char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */
174 char fw_version[32]; /* Firmware revision */
175 unsigned short base_addr; /* HW Base I/O address */
176 unsigned char irq; /* HW irq line */
177 char iwproto[IFNAMSIZ + 1]; /* Wireless/protocol name */
178 int pcmcia_slot; /* Pcmcia slot */
179 char * sysfs[SYSFS_MAX_FILE]; /* sysfs selectors */
182 /* Extra parsing information when adding a mapping */
183 typedef struct add_extra
185 char * modif_pos; /* Descriptor modifier */
189 /* Prototype for adding a selector to a mapping. Return -1 if invalid value. */
190 typedef int (*mapping_add)(struct if_mapping * ifnode,
194 struct add_extra * extra,
197 /* Prototype for comparing the selector of two mapping. Return 0 if matches. */
198 typedef int (*mapping_cmp)(struct if_mapping * ifnode,
199 struct if_mapping * target);
200 /* Prototype for extracting selector value from live interface */
201 typedef int (*mapping_get)(int skfd,
203 struct if_mapping * target,
206 /* How to handle a selector */
207 typedef struct mapping_selector
215 /* sysfs global data */
216 typedef struct sysfs_metadata
218 char * root; /* Root of the sysfs */
219 int rlen; /* Size of it */
220 int filenum; /* Number of files */
221 char * filename[SYSFS_MAX_FILE]; /* Name of files */
224 /**************************** PROTOTYPES ****************************/
227 mapping_addmac(struct if_mapping * ifnode,
231 struct add_extra * extra,
234 mapping_cmpmac(struct if_mapping * ifnode,
235 struct if_mapping * target);
237 mapping_getmac(int skfd,
239 struct if_mapping * target,
242 mapping_addarp(struct if_mapping * ifnode,
246 struct add_extra * extra,
249 mapping_cmparp(struct if_mapping * ifnode,
250 struct if_mapping * target);
252 mapping_getarp(int skfd,
254 struct if_mapping * target,
257 mapping_adddriver(struct if_mapping * ifnode,
261 struct add_extra * extra,
264 mapping_cmpdriver(struct if_mapping * ifnode,
265 struct if_mapping * target);
267 mapping_addbusinfo(struct if_mapping * ifnode,
271 struct add_extra * extra,
274 mapping_cmpbusinfo(struct if_mapping * ifnode,
275 struct if_mapping * target);
277 mapping_addfirmware(struct if_mapping * ifnode,
281 struct add_extra * extra,
284 mapping_cmpfirmware(struct if_mapping * ifnode,
285 struct if_mapping * target);
287 mapping_getdriverbusinfo(int skfd,
289 struct if_mapping * target,
292 mapping_addbaseaddr(struct if_mapping * ifnode,
296 struct add_extra * extra,
299 mapping_cmpbaseaddr(struct if_mapping * ifnode,
300 struct if_mapping * target);
302 mapping_addirq(struct if_mapping * ifnode,
306 struct add_extra * extra,
309 mapping_cmpirq(struct if_mapping * ifnode,
310 struct if_mapping * target);
312 mapping_getbaseaddrirq(int skfd,
314 struct if_mapping * target,
317 mapping_addiwproto(struct if_mapping * ifnode,
321 struct add_extra * extra,
324 mapping_cmpiwproto(struct if_mapping * ifnode,
325 struct if_mapping * target);
327 mapping_getiwproto(int skfd,
329 struct if_mapping * target,
332 mapping_addpcmciaslot(struct if_mapping * ifnode,
336 struct add_extra * extra,
339 mapping_cmppcmciaslot(struct if_mapping * ifnode,
340 struct if_mapping * target);
342 mapping_getpcmciaslot(int skfd,
344 struct if_mapping * target,
347 mapping_addsysfs(struct if_mapping * ifnode,
351 struct add_extra * extra,
354 mapping_cmpsysfs(struct if_mapping * ifnode,
355 struct if_mapping * target);
357 mapping_getsysfs(int skfd,
359 struct if_mapping * target,
362 /**************************** VARIABLES ****************************/
364 /* List of mapping read for config file */
365 struct if_mapping * mapping_list = NULL;
367 /* List of selectors we can handle */
368 const struct mapping_selector selector_list[] =
370 /* MAC address and ARP/Link type from ifconfig */
371 { "mac", &mapping_addmac, &mapping_cmpmac, &mapping_getmac },
372 { "ethaddr", &mapping_addmac, &mapping_cmpmac, &mapping_getmac },
373 { "arp", &mapping_addarp, &mapping_cmparp, &mapping_getarp },
374 { "linktype", &mapping_addarp, &mapping_cmparp, &mapping_getarp },
375 /* Driver name, Bus-Info and firmware rev from ethtool -i */
376 { "driver", &mapping_adddriver, &mapping_cmpdriver,
377 &mapping_getdriverbusinfo },
378 { "businfo", &mapping_addbusinfo, &mapping_cmpbusinfo,
379 &mapping_getdriverbusinfo },
380 { "firmware", &mapping_addfirmware, &mapping_cmpfirmware,
381 &mapping_getdriverbusinfo },
382 /* Base Address and IRQ from ifconfig */
383 { "baseaddress", &mapping_addbaseaddr, &mapping_cmpbaseaddr,
384 &mapping_getbaseaddrirq },
385 { "irq", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq },
386 { "interrupt", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq },
387 /* Wireless Protocol from iwconfig */
388 { "iwproto", &mapping_addiwproto, &mapping_cmpiwproto, &mapping_getiwproto },
389 /* Pcmcia slot from cardmgr */
390 { "pcmciaslot", &mapping_addpcmciaslot, &mapping_cmppcmciaslot, &mapping_getpcmciaslot },
391 /* sysfs file (udev emulation) */
392 { "sysfs", &mapping_addsysfs, &mapping_cmpsysfs, &mapping_getsysfs },
394 { NULL, NULL, NULL, NULL },
396 const int selector_num = sizeof(selector_list)/sizeof(selector_list[0]);
398 /* List of active selectors */
399 int selector_active[SELECT_NUM]; /* Selectors active */
402 * All the following flags are controlled by the command line switches...
403 * It's a bit hackish to have them all as global, so maybe we should pass
404 * them in a big struct as function arguments... More complex and
405 * probably not worth it ?
408 /* Invocation type */
409 int print_newname = 0;
410 char * new_name = NULL;
412 /* Takeover support */
413 int force_takeover = 0; /* Takeover name from other interface */
414 int num_takeover = 0; /* Number of takeover done */
416 /* Dry-run support */
417 int dry_run = 0; /* Just print new name, don't rename */
419 /* Verbose support (i.e. debugging) */
422 /* sysfs global data */
423 struct sysfs_metadata sysfs_global =
426 0, { NULL, NULL, NULL, NULL, NULL },
429 /******************** INTERFACE NAME MANAGEMENT ********************/
431 * Bunch of low level function for managing interface names.
434 /*------------------------------------------------------------------*/
436 * Compare two interface names, with wildcards.
437 * We can't use fnmatch() because we don't want expansion of '[...]'
438 * expressions, '\' sequences and matching of '.'.
439 * We only want to match a single '*' (converted to a %d at that point)
440 * to a numerical value (no ascii).
441 * Return 0 is matches.
444 if_match_ifname(const char * pattern,
452 /* Check for a wildcard (converted from '*' to '%d' in mapping_create()) */
453 p = strstr(pattern, "%d");
455 /* No wildcard, simple comparison */
457 return(strcmp(pattern, value));
459 /* Check is prefixes match */
461 ret = strncmp(pattern, value, n);
465 /* Check that value has some digits at this point */
470 /* Skip digits to go to value suffix */
478 /* Compare suffixes */
479 return(strcmp(p, v));
482 /*------------------------------------------------------------------*/
484 * Steal interface name from another interface. This enable interface
487 * 1) with kernel 2.6.X
488 * 2) if other interface is down
489 * Because of (2), it won't work with hotplug, but we don't need it
490 * with hotplug, only with static ifaces...
493 if_takeover_name(int skfd,
494 const char * victimname)
496 char autoname[IFNAMSIZ+1];
501 /* Compute name for victim interface */
502 len = strlen(victimname);
503 memcpy(autoname, victimname, len + 1);
504 if(len > (IFNAMSIZ - 2))
505 len = IFNAMSIZ - 2; /* Make sure we have at least two char */
506 len--; /* Convert to index */
507 while(isdigit(autoname[len]))
508 len--; /* Scrap all trailing digits */
509 strcpy(autoname + len + 1, "%d");
512 fprintf(stderr, "Takeover : moving interface `%s' to `%s'.\n",
513 victimname, autoname);
515 /* Prepare request */
516 bzero(&ifr, sizeof(struct ifreq));
517 strncpy(ifr.ifr_name, victimname, IFNAMSIZ);
518 strncpy(ifr.ifr_newname, autoname, IFNAMSIZ);
520 /* Rename victim interface */
521 ret = ioctl(skfd, SIOCSIFNAME, &ifr);
529 /*------------------------------------------------------------------*/
531 * Ask the kernel to change the name of an interface.
532 * That's what we want to do. All the rest is to make sure we call this
536 if_set_name(int skfd,
537 const char * oldname,
538 const char * newname,
544 /* The kernel doesn't check is the interface already has the correct
545 * name and may return an error, so check ourselves.
546 * In the case of wildcard, the result can be weird : if oldname='eth0'
547 * and newname='eth*', retname would be 'eth1'.
548 * So, if the oldname value matches the newname pattern, just return
550 if(!if_match_ifname(newname, oldname))
553 fprintf(stderr, "Setting : Interface `%s' already matches `%s'.\n",
556 strcpy(retname, oldname);
560 /* Prepare request */
561 bzero(&ifr, sizeof(struct ifreq));
562 strncpy(ifr.ifr_name, oldname, IFNAMSIZ);
563 strncpy(ifr.ifr_newname, newname, IFNAMSIZ);
566 ret = ioctl(skfd, SIOCSIFNAME, &ifr);
568 /* Takeover support : grab interface name from another interface */
569 if(ret && (errno == EEXIST) && force_takeover)
571 /* Push things around */
572 ret = if_takeover_name(skfd, newname);
575 ret = ioctl(skfd, SIOCSIFNAME, &ifr);
580 /* Get the real new name (in case newname is a wildcard) */
581 strcpy(retname, ifr.ifr_newname);
584 fprintf(stderr, "Setting : Interface `%s' renamed to `%s'.\n",
591 /************************ SELECTOR HANDLING ************************/
593 * Handle the various selector we support
596 /*------------------------------------------------------------------*/
598 * Add a MAC address selector to a mapping
601 mapping_addmac(struct if_mapping * ifnode,
605 struct add_extra * extra,
610 /* Avoid "Unused parameter" warning */
613 /* Verify validity of string */
614 if(len >= sizeof(ifnode->mac_filter))
616 fprintf(stderr, "MAC address too long at line %d\n", linenum);
619 n = strspn(string, "0123456789ABCDEFabcdef:*");
622 fprintf(stderr, "Error: Invalid MAC address `%s' at line %d\n",
627 /* Copy as filter in all cases */
628 memcpy(ifnode->mac_filter, string, len + 1);
630 /* Check the type of MAC address */
631 if (strchr(ifnode->mac_filter, '*') != NULL)
633 /* This is a wilcard. Usual format : "01:23:45:*"
634 * Unfortunately, we can't do proper parsing. */
635 ifnode->active[SELECT_MAC] = HAS_MAC_FILTER;
636 active[SELECT_MAC] = HAS_MAC_FILTER;
640 /* Not a wildcard : "01:23:45:67:89:AB" */
641 ifnode->mac_len = iw_mac_aton(ifnode->mac_filter,
642 ifnode->mac, MAX_MAC_LEN);
643 if(ifnode->mac_len == 0)
645 fprintf(stderr, "Error: Invalid MAC address `%s' at line %d\n",
646 ifnode->mac_filter, linenum);
650 /* Check that it's not NULL */
651 if((ifnode->mac_len == 6) && (!memcmp(&ifnode->mac, &zero_mac, 6)))
654 "Warning: MAC address is null at line %d, this is dangerous...\n",
658 ifnode->active[SELECT_MAC] = HAS_MAC_EXACT;
659 if(active[SELECT_MAC] == 0)
660 active[SELECT_MAC] = HAS_MAC_EXACT;
665 "Parsing : Added %s MAC address `%s' from line %d.\n",
666 ifnode->active[SELECT_MAC] == HAS_MAC_FILTER ? "filter" : "exact",
667 ifnode->mac_filter, linenum);
672 /*------------------------------------------------------------------*/
674 * Compare the mac address of two mappings
677 mapping_cmpmac(struct if_mapping * ifnode,
678 struct if_mapping * target)
680 /* Check for wildcard matching */
681 if(ifnode->active[SELECT_MAC] == HAS_MAC_FILTER)
682 /* Do wildcard matching, case insensitive */
683 return(fnmatch(ifnode->mac_filter, target->mac_filter, FNM_CASEFOLD));
685 /* Exact matching, in hex */
686 return((ifnode->mac_len != target->mac_len) ||
687 memcmp(ifnode->mac, target->mac, ifnode->mac_len));
690 /*------------------------------------------------------------------*/
692 * Extract the MAC address and Link Type of an interface
695 mapping_getmac(int skfd,
697 struct if_mapping * target,
704 /* Get MAC address */
705 bzero(&ifr, sizeof(struct ifreq));
706 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
707 ret = ioctl(skfd, SIOCGIFHWADDR, &ifr);
710 fprintf(stderr, "Error: Can't read MAC address on interface `%s' : %s\n",
711 ifname, strerror(errno));
715 /* Extract ARP type */
716 target->hw_type = ifr.ifr_hwaddr.sa_family;
717 /* Calculate address length */
719 for(i = 0; i < weird_mac_len_num; i++)
720 if(weird_mac_len[i][0] == ifr.ifr_hwaddr.sa_family)
722 target->mac_len = weird_mac_len[i][1];
725 /* Extract MAC address bytes */
726 memcpy(target->mac, ifr.ifr_hwaddr.sa_data, target->mac_len);
728 /* Check the type of comparison */
729 if((flag == HAS_MAC_FILTER) || verbose)
731 /* Convert to ASCII */
732 iw_mac_ntop(target->mac, target->mac_len,
733 target->mac_filter, sizeof(target->mac_filter));
736 target->active[SELECT_MAC] = flag;
737 target->active[SELECT_ARP] = 1;
741 "Querying %s : Got MAC address `%s' and ARP/Link Type `%d'.\n",
742 ifname, target->mac_filter, target->hw_type);
747 /*------------------------------------------------------------------*/
749 * Add a ARP/Link type selector to a mapping
752 mapping_addarp(struct if_mapping * ifnode,
756 struct add_extra * extra,
762 /* Avoid "Unused parameter" warning */
765 /* Verify validity of string, convert to int */
766 n = strspn(string, "0123456789");
767 if((n < len) || (sscanf(string, "%d", &type) != 1))
769 fprintf(stderr, "Error: Invalid ARP/Link Type `%s' at line %d\n",
774 ifnode->hw_type = (unsigned short) type;
775 ifnode->active[SELECT_ARP] = 1;
776 active[SELECT_ARP] = 1;
779 fprintf(stderr, "Parsing : Added ARP/Link Type `%d' from line %d.\n",
780 ifnode->hw_type, linenum);
785 /*------------------------------------------------------------------*/
787 * Compare the ARP/Link type of two mappings
790 mapping_cmparp(struct if_mapping * ifnode,
791 struct if_mapping * target)
793 return(!(ifnode->hw_type == target->hw_type));
796 /*------------------------------------------------------------------*/
798 * Extract the ARP/Link type of an interface
801 mapping_getarp(int skfd,
803 struct if_mapping * target,
806 /* We may have already extracted the MAC address */
807 if(target->active[SELECT_MAC])
810 /* Otherwise just do it */
811 return(mapping_getmac(skfd, ifname, target, flag));
814 /*------------------------------------------------------------------*/
816 * Add a Driver name selector to a mapping
819 mapping_adddriver(struct if_mapping * ifnode,
823 struct add_extra * extra,
826 /* Avoid "Unused parameter" warning */
829 /* Plain string, minimal verification */
830 if(len >= sizeof(ifnode->driver))
832 fprintf(stderr, "Error: Driver name too long at line %d\n", linenum);
837 memcpy(ifnode->driver, string, len + 1);
840 ifnode->active[SELECT_DRIVER] = 1;
841 active[SELECT_DRIVER] = 1;
845 "Parsing : Added Driver name `%s' from line %d.\n",
846 ifnode->driver, linenum);
851 /*------------------------------------------------------------------*/
853 * Compare the Driver name of two mappings
856 mapping_cmpdriver(struct if_mapping * ifnode,
857 struct if_mapping * target)
859 /* Do wildcard matching, case insensitive */
860 return(fnmatch(ifnode->driver, target->driver, FNM_CASEFOLD));
863 /*------------------------------------------------------------------*/
865 * Add a Bus-Info selector to a mapping
868 mapping_addbusinfo(struct if_mapping * ifnode,
872 struct add_extra * extra,
879 /* Avoid "Unused parameter" warning */
882 /* Verify validity of string */
883 if(len >= sizeof(ifnode->bus_info))
885 fprintf(stderr, "Bus Info too long at line %d\n", linenum);
889 /* Hum... This doesn's seem true for non-PCI bus-info */
890 n = strspn(string, "0123456789ABCDEFabcdef:.*");
893 fprintf(stderr, "Error: Invalid Bus Info `%s' at line %d\n",
900 memcpy(ifnode->bus_info, string, len + 1);
903 ifnode->active[SELECT_BUSINFO] = 1;
904 active[SELECT_BUSINFO] = 1;
908 "Parsing : Added Bus Info `%s' from line %d.\n",
909 ifnode->bus_info, linenum);
914 /*------------------------------------------------------------------*/
916 * Compare the Bus-Info of two mappings
919 mapping_cmpbusinfo(struct if_mapping * ifnode,
920 struct if_mapping * target)
922 /* Do wildcard matching, case insensitive */
923 return(fnmatch(ifnode->bus_info, target->bus_info, FNM_CASEFOLD));
926 /*------------------------------------------------------------------*/
928 * Add a Firmare revision selector to a mapping
931 mapping_addfirmware(struct if_mapping * ifnode,
935 struct add_extra * extra,
938 /* Avoid "Unused parameter" warning */
941 /* Verify validity of string */
942 if(len >= sizeof(ifnode->fw_version))
944 fprintf(stderr, "Firmware revision too long at line %d\n", linenum);
949 memcpy(ifnode->fw_version, string, len + 1);
952 ifnode->active[SELECT_FIRMWARE] = 1;
953 active[SELECT_FIRMWARE] = 1;
957 "Parsing : Added Firmware Revision `%s' from line %d.\n",
958 ifnode->fw_version, linenum);
963 /*------------------------------------------------------------------*/
965 * Compare the Bus-Info of two mappings
968 mapping_cmpfirmware(struct if_mapping * ifnode,
969 struct if_mapping * target)
971 /* Do wildcard matching, case insensitive */
972 return(fnmatch(ifnode->fw_version, target->fw_version, FNM_CASEFOLD));
975 /*------------------------------------------------------------------*/
977 * Extract the Driver name and Bus-Info from a live interface
980 mapping_getdriverbusinfo(int skfd,
982 struct if_mapping * target,
986 struct ethtool_drvinfo drvinfo;
989 /* Avoid "Unused parameter" warning */
992 /* We may come here twice or more, so do the job only once */
993 if(target->active[SELECT_DRIVER] || target->active[SELECT_BUSINFO]
994 || target->active[SELECT_FIRMWARE])
997 /* Prepare request */
998 bzero(&ifr, sizeof(struct ifreq));
999 bzero(&drvinfo, sizeof(struct ethtool_drvinfo));
1000 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1001 drvinfo.cmd = ETHTOOL_GDRVINFO;
1002 ifr.ifr_data = (caddr_t) &drvinfo;
1005 ret = ioctl(skfd, SIOCETHTOOL, &ifr);
1008 /* Most drivers don't support that, keep quiet for now */
1011 "Error: Can't read driver/bus-info on interface `%s' : %s\n",
1012 ifname, strerror(errno));
1017 strcpy(target->driver, drvinfo.driver);
1018 strcpy(target->bus_info, drvinfo.bus_info);
1019 strcpy(target->fw_version, drvinfo.fw_version);
1022 target->active[SELECT_DRIVER] = 1;
1023 target->active[SELECT_BUSINFO] = 1;
1024 target->active[SELECT_FIRMWARE] = 1;
1028 "Querying %s : Got Driver name `%s', Bus Info `%s' and Firmware `%s'.\n",
1029 ifname, target->driver, target->bus_info, target->fw_version);
1034 /*------------------------------------------------------------------*/
1036 * Add a Base Address selector to a mapping
1039 mapping_addbaseaddr(struct if_mapping * ifnode,
1043 struct add_extra * extra,
1047 unsigned int address;
1049 /* Avoid "Unused parameter" warning */
1052 /* Verify validity of string */
1053 n = strspn(string, "0123456789ABCDEFabcdefx");
1054 if((n < len) || (sscanf(string, "0x%X", &address) != 1))
1056 fprintf(stderr, "Error: Invalid Base Address `%s' at line %d\n",
1062 ifnode->base_addr = (unsigned short) address;
1065 ifnode->active[SELECT_BASEADDR] = 1;
1066 active[SELECT_BASEADDR] = 1;
1070 "Parsing : Added Base Address `0x%X' from line %d.\n",
1071 ifnode->base_addr, linenum);
1076 /*------------------------------------------------------------------*/
1078 * Compare the Base Address of two mappings
1081 mapping_cmpbaseaddr(struct if_mapping * ifnode,
1082 struct if_mapping * target)
1084 /* Do wildcard matching, case insensitive */
1085 return(!(ifnode->base_addr == target->base_addr));
1088 /*------------------------------------------------------------------*/
1090 * Add a IRQ selector to a mapping
1093 mapping_addirq(struct if_mapping * ifnode,
1097 struct add_extra * extra,
1103 /* Avoid "Unused parameter" warning */
1106 /* Verify validity of string */
1107 n = strspn(string, "0123456789");
1108 if((n < len) || (sscanf(string, "%d", &irq) != 1))
1110 fprintf(stderr, "Error: Invalid Base Address `%s' at line %d\n",
1116 ifnode->irq = (unsigned char) irq;
1119 ifnode->active[SELECT_IRQ] = 1;
1120 active[SELECT_IRQ] = 1;
1124 "Parsing : Added IRQ `%d' from line %d.\n",
1125 ifnode->irq, linenum);
1130 /*------------------------------------------------------------------*/
1132 * Compare the IRQ of two mappings
1135 mapping_cmpirq(struct if_mapping * ifnode,
1136 struct if_mapping * target)
1138 /* Do wildcard matching, case insensitive */
1139 return(!(ifnode->irq == target->irq));
1142 /*------------------------------------------------------------------*/
1144 * Extract the Driver name and Bus-Info from a live interface
1147 mapping_getbaseaddrirq(int skfd,
1148 const char * ifname,
1149 struct if_mapping * target,
1153 struct ifmap map; /* hardware setup */
1156 /* Avoid "Unused parameter" warning */
1159 /* We may come here twice, so do the job only once */
1160 if(target->active[SELECT_BASEADDR] || target->active[SELECT_IRQ])
1163 /* Prepare request */
1164 bzero(&ifr, sizeof(struct ifreq));
1165 bzero(&map, sizeof(struct ifmap));
1166 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1169 ret = ioctl(skfd, SIOCGIFMAP, &ifr);
1172 /* Don't know if every interface has that, so keep quiet... */
1175 "Error: Can't read base address/irq on interface `%s' : %s\n",
1176 ifname, strerror(errno));
1180 /* Copy over, activate */
1181 if(ifr.ifr_map.base_addr >= 0x100)
1183 target->base_addr = ifr.ifr_map.base_addr;
1184 target->active[SELECT_BASEADDR] = 1;
1186 target->irq = ifr.ifr_map.irq;
1187 target->active[SELECT_IRQ] = 1;
1191 "Querying %s : Got Base Address `0x%X' and IRQ `%d'.\n",
1192 ifname, target->base_addr, target->irq);
1197 /*------------------------------------------------------------------*/
1199 * Add a Wireless Protocol selector to a mapping
1202 mapping_addiwproto(struct if_mapping * ifnode,
1206 struct add_extra * extra,
1209 /* Avoid "Unused parameter" warning */
1212 /* Verify validity of string */
1213 if(len >= sizeof(ifnode->iwproto))
1215 fprintf(stderr, "Wireless Protocol too long at line %d\n", linenum);
1220 memcpy(ifnode->iwproto, string, len + 1);
1223 ifnode->active[SELECT_IWPROTO] = 1;
1224 active[SELECT_IWPROTO] = 1;
1228 "Parsing : Added Wireless Protocol `%s' from line %d.\n",
1229 ifnode->iwproto, linenum);
1234 /*------------------------------------------------------------------*/
1236 * Compare the Wireless Protocol of two mappings
1239 mapping_cmpiwproto(struct if_mapping * ifnode,
1240 struct if_mapping * target)
1242 /* Do wildcard matching, case insensitive */
1243 return(fnmatch(ifnode->iwproto, target->iwproto, FNM_CASEFOLD));
1246 /*------------------------------------------------------------------*/
1248 * Extract the Wireless Protocol from a live interface
1251 mapping_getiwproto(int skfd,
1252 const char * ifname,
1253 struct if_mapping * target,
1258 /* Avoid "Unused parameter" warning */
1261 /* Get wireless name */
1262 if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
1263 /* Don't complain about it, Ethernet cards will never support this */
1266 strncpy(target->iwproto, wrq.u.name, IFNAMSIZ);
1267 target->iwproto[IFNAMSIZ] = '\0';
1270 target->active[SELECT_IWPROTO] = 1;
1274 "Querying %s : Got Wireless Protocol `%s'.\n",
1275 ifname, target->iwproto);
1280 /*------------------------------------------------------------------*/
1282 * Add a Pcmcia Slot selector to a mapping
1285 mapping_addpcmciaslot(struct if_mapping * ifnode,
1289 struct add_extra * extra,
1294 /* Avoid "Unused parameter" warning */
1297 /* Verify validity of string, convert to int */
1298 n = strspn(string, "0123456789");
1299 if((n < len) || (sscanf(string, "%d", &ifnode->pcmcia_slot) != 1))
1301 fprintf(stderr, "Error: Invalid Pcmcia Slot `%s' at line %d\n",
1306 ifnode->active[SELECT_PCMCIASLOT] = 1;
1307 active[SELECT_PCMCIASLOT] = 1;
1310 fprintf(stderr, "Parsing : Added Pcmcia Slot `%d' from line %d.\n",
1311 ifnode->pcmcia_slot, linenum);
1316 /*------------------------------------------------------------------*/
1318 * Compare the Pcmcia Slot of two mappings
1321 mapping_cmppcmciaslot(struct if_mapping * ifnode,
1322 struct if_mapping * target)
1324 return(!(ifnode->pcmcia_slot == target->pcmcia_slot));
1327 /*------------------------------------------------------------------*/
1329 * Extract the Pcmcia Slot of an interface
1330 * Note that this works only for cards fully managed by cardmgr.
1331 * With the kernel pcmcia modules, 32 bits cards (CardBus) are not managed
1332 * by cardmgr, and therefore won't have a valid slot number. For those
1333 * cards, you should use Bus Info (when the driver exports it).
1334 * In the long term, 16 bits card as well will no longer be managed by
1335 * cardmgr. Currently, Bus Info for 16 bit cards don't have any information
1336 * enabling to locate their physical location on the system, but I hope that
1338 * When that happen, we can drop this code...
1341 mapping_getpcmciaslot(int skfd,
1342 const char * ifname,
1343 struct if_mapping * target,
1347 char * linebuf = NULL;
1351 /* Avoid "Unused parameter" warning */
1355 /* Open the stab file for reading */
1356 stream = fopen(PCMCIA_STAB1, "r");
1359 /* Try again, alternate location */
1360 stream = fopen(PCMCIA_STAB2, "r");
1363 fprintf(stderr, "Error: Can't open PCMCIA Stab file `%s' or `%s': %s\n",
1364 PCMCIA_STAB1, PCMCIA_STAB2, strerror(errno));
1369 /* Read each line of file
1370 * getline is a GNU extension :-( The buffer is recycled and increased
1371 * as needed by getline. */
1372 while(getline(&linebuf, &linelen, stream) > 0)
1380 /* Keep track of line number */
1383 /* Get Pcmcia socket number */
1388 continue; /* Line ended */
1389 n = strcspn(p, " \t\n");
1390 k = strspn(p, "0123456789");
1391 if((k < n) || (sscanf(p, "%d", &pcmcia_slot) != 1))
1395 /* Skip socket number */
1396 /* Skip socket number ; device class ; driver name ; instance */
1397 for(i = 0; i < 4; i++)
1402 p += strspn(p, " \t\n");
1404 break; /* Line ended */
1405 /* Next item size */
1406 n = strcspn(p, " \t\n");
1409 continue; /* Line ended */
1411 /* Terminate dev name */
1414 /* Compare to interface name */
1415 if(!strcmp(p, ifname))
1418 target->pcmcia_slot = pcmcia_slot;
1421 target->active[SELECT_PCMCIASLOT] = 1;
1425 "Querying %s : Got Pcmcia Slot `%d'.\n",
1426 ifname, target->pcmcia_slot);
1427 /* Exit loop, found it */
1431 /* Finished -> next line */
1438 return(target->active[SELECT_PCMCIASLOT] ? 0 : -1);
1441 /*------------------------------------------------------------------*/
1443 * Add a sysfs selector to a mapping
1446 mapping_addsysfs(struct if_mapping * ifnode,
1450 struct add_extra * extra,
1453 int findex; /* filename index */
1456 /* Check if we have a modifier */
1457 if((extra == NULL) || (extra->modif_pos == NULL))
1459 fprintf(stderr, "Error: No SYSFS filename at line %d\n", linenum);
1463 /* Search if the filename already exist */
1464 for(findex = 0; findex < sysfs_global.filenum; findex++)
1466 if(!strcmp(extra->modif_pos, sysfs_global.filename[findex]))
1470 /* If filename does not exist, creates it */
1471 if(findex == sysfs_global.filenum)
1473 if(findex == SYSFS_MAX_FILE)
1475 fprintf(stderr, "Error: Too many SYSFS filenames at line %d\n", linenum);
1478 sdup = strndup(extra->modif_pos, extra->modif_len);
1481 fprintf(stderr, "Error: Can't allocate SYSFS file\n");
1484 sysfs_global.filename[findex] = sdup;
1485 sysfs_global.filenum++;
1489 sdup = strndup(string, len);
1492 fprintf(stderr, "Error: Can't allocate SYSFS value\n");
1495 ifnode->sysfs[findex] = sdup;
1498 ifnode->active[SELECT_SYSFS] = 1;
1499 active[SELECT_SYSFS] = 1;
1503 "Parsing : Added SYSFS filename `%s' value `%s' from line %d.\n",
1504 sysfs_global.filename[findex], ifnode->sysfs[findex], linenum);
1509 /*------------------------------------------------------------------*/
1511 * Compare all the sysfs values of two mappings
1514 mapping_cmpsysfs(struct if_mapping * ifnode,
1515 struct if_mapping * target)
1517 int findex; /* filename index */
1520 /* Loop on all sysfs selector */
1521 for(findex = 0; findex < sysfs_global.filenum; findex++)
1523 /* If the mapping defines this sysfs selector.. */
1524 if(ifnode->sysfs[findex] != NULL)
1525 /* And if the sysfs values don't match */
1526 if((target->sysfs[findex] == NULL) ||
1527 (fnmatch(ifnode->sysfs[findex], target->sysfs[findex],
1529 /* Then the sysfs selector doesn't match */
1536 /*------------------------------------------------------------------*/
1538 * Extract all the sysfs values of an interface
1541 mapping_getsysfs(int skfd,
1542 const char * ifname,
1543 struct if_mapping * target,
1547 char * linebuf = NULL;
1550 int findex; /* filename index */
1552 /* Avoid "Unused parameter" warning */
1556 /* Check if we know the root of the sysfs filesystem */
1557 if(sysfs_global.root == NULL)
1559 /* Open the mount file for reading */
1560 stream = fopen("/proc/mounts", "r");
1563 fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n",
1568 /* Read each line of file
1569 * getline is a GNU extension :-( The buffer is recycled and increased
1570 * as needed by getline. */
1571 while(getline(&linebuf, &linelen, stream) > 0)
1576 /* Get the line starting with sysfs */
1580 if(!strncasecmp(p, "sysfs ", 6))
1582 /* Find the mount point */
1586 n = strcspn(p, " \t\n");
1587 sdup = strndup(p, n);
1588 if((n == 0) || (sdup == NULL))
1590 fprintf(stderr, "Error: Can't parse /proc/mounts file: %s\n",
1595 sysfs_global.root = sdup;
1596 sysfs_global.rlen = n;
1599 /* Finished -> next line */
1605 /* Check if we found it */
1606 if(sysfs_global.root == NULL)
1608 fprintf(stderr, "Error: Can't find sysfs in /proc/mounts file\n");
1614 /* Loop on all sysfs selector */
1615 for(findex = 0; findex < sysfs_global.filenum; findex++)
1622 /* Construct complete filename for the sysfs selector */
1623 flen = (sysfs_global.rlen + 11 + strlen(ifname) + 1 +
1624 strlen(sysfs_global.filename[findex]) + 1);
1625 fname = malloc(flen);
1628 fprintf(stderr, "Error: Can't allocate SYSFS filename\n");
1632 sprintf(fname, "%s/class/net/%s/%s", sysfs_global.root, ifname,
1633 sysfs_global.filename[findex]);
1635 /* Open the sysfs file for reading */
1636 stream = fopen(fname, "r");
1639 /* Some sysfs attribute may no exist for some interface */
1641 fprintf(stderr, "Error: Can't open file `%s': %s\n", fname,
1643 /* Next sysfs selector */
1647 /* Read file. Only one line in file. */
1648 n = getline(&linebuf, &linelen, stream);
1652 /* Some sysfs attribute are void for some interface */
1654 fprintf(stderr, "Error: Can't read file `%s'\n", fname);
1655 /* Next sysfs selector */
1659 /* Get content, remove trailing '/n', save it */
1661 if(p[n - 1] == '\n')
1663 sdup = strndup(p, n);
1666 fprintf(stderr, "Error: Can't allocate SYSFS value\n");
1670 target->sysfs[findex] = sdup;
1673 target->active[SELECT_SYSFS] = 1;
1677 "Querying %s : Got SYSFS filename `%s' value `%s'.\n",
1678 ifname, sysfs_global.filename[findex], target->sysfs[findex]);
1680 /* Finished : Next sysfs selector */
1686 return(target->active[SELECT_SYSFS] ? 0 : -1);
1690 /*********************** MAPPING MANAGEMENTS ***********************/
1692 * Manage interface mappings.
1693 * Each mapping tell us how to identify a specific interface name.
1694 * It is composed of a bunch of selector values.
1697 /*------------------------------------------------------------------*/
1699 * Create a new interface mapping and verify its name
1701 static struct if_mapping *
1702 mapping_create(char * pos,
1706 struct if_mapping * ifnode;
1709 /* Check overflow. */
1712 fprintf(stderr, "Error: Interface name `%.*s' too long at line %d\n",
1713 (int) len, pos, linenum);
1717 /* Create mapping, zero it */
1718 ifnode = calloc(1, sizeof(if_mapping));
1721 fprintf(stderr, "Error: Can't allocate interface mapping.\n");
1725 /* Set the name, terminates it */
1726 memcpy(ifnode->ifname, pos, len);
1727 ifnode->ifname[len] = '\0';
1729 /* Check the interface name and issue various pedantic warnings.
1730 * We assume people using takeover want to force interfaces to those
1731 * names and know what they are doing, so don't bother them... */
1732 if((!force_takeover) &&
1733 ((!strcmp(ifnode->ifname, "eth0")) || (!strcmp(ifnode->ifname, "wlan0"))))
1735 "Warning: Interface name is `%s' at line %d, can't be mapped reliably.\n",
1736 ifnode->ifname, linenum);
1737 if(strchr(ifnode->ifname, ':'))
1738 fprintf(stderr, "Warning: Alias device `%s' at line %d probably can't be mapped.\n",
1739 ifnode->ifname, linenum);
1741 /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
1742 * This require specific kernel support (2.6.2-rc1 and later).
1743 * We externally use '*', but the kernel doesn't know about that,
1744 * so convert it to something it knows about... */
1745 star = strchr(ifnode->ifname, '*');
1748 /* We need an extra char */
1752 "Error: Interface wildcard `%s' too long at line %d\n",
1753 ifnode->ifname, linenum);
1758 /* Replace '*' with '%d' */
1759 memmove(star + 2, star + 1, len + 1 - (star - ifnode->ifname));
1765 fprintf(stderr, "Parsing : Added Mapping `%s' from line %d.\n",
1766 ifnode->ifname, linenum);
1772 /*------------------------------------------------------------------*/
1774 * Find the most appropriate selector matching a given selector name
1776 static inline const struct mapping_selector *
1777 selector_find(const char * string,
1781 const struct mapping_selector * found = NULL;
1785 /* Go through all selectors */
1786 for(i = 0; selector_list[i].name != NULL; ++i)
1788 /* No match -> next one */
1789 if(strncasecmp(selector_list[i].name, string, slen) != 0)
1792 /* Exact match -> perfect */
1793 if(slen == strlen(selector_list[i].name))
1794 return &selector_list[i];
1799 found = &selector_list[i];
1802 if (selector_list[i].add_fn != found->add_fn)
1808 fprintf(stderr, "Error: Unknown selector `%.*s' at line %d.\n",
1809 (int) slen, string, linenum);
1815 fprintf(stderr, "Selector `%.*s'at line %d is ambiguous.\n",
1816 (int) slen, string, linenum);
1823 /*------------------------------------------------------------------*/
1825 * Read the configuration file and extract all valid mappings and their
1829 mapping_readfile(const char * filename)
1832 char * linebuf = NULL;
1835 struct add_extra extrainfo;
1837 /* Reset the list of filters */
1838 bzero(selector_active, sizeof(selector_active));
1840 /* Check filename */
1841 if(!strcmp(filename, "-"))
1843 /* Read from stdin */
1849 /* Open the file for reading */
1850 stream = fopen(filename, "r");
1853 fprintf(stderr, "Error: Can't open configuration file `%s': %s\n",
1854 filename, strerror(errno));
1859 /* Read each line of file
1860 * getline is a GNU extension :-( The buffer is recycled and increased
1861 * as needed by getline. */
1862 while(getline(&linebuf, &linelen, stream) > 0)
1864 struct if_mapping * ifnode;
1868 int ret = -13; /* Complain if no selectors */
1870 /* Keep track of line number */
1873 /* Every comments terminates parsing */
1874 if((p = strchr(linebuf,'#')) != NULL)
1877 /* Get interface name */
1882 continue; /* Line ended */
1883 n = strcspn(p, " \t\n");
1885 /* Create mapping */
1886 ifnode = mapping_create(p, n, linenum);
1888 continue; /* Ignore this line */
1890 p += strspn(p, " \t\n");
1892 /* Loop on all selectors */
1895 const struct mapping_selector * selector = NULL;
1896 struct add_extra * extra = NULL;
1898 /* Selector name length - stop at modifier start */
1899 n = strcspn(p, " \t\n{");
1902 selector = selector_find(p, n, linenum);
1910 /* Check for modifier */
1914 /* Find end of modifier */
1919 "Error: unterminated selector modifier value on line %d\n",
1922 break; /* Line ended */
1924 /* Fill in struct and hook it */
1925 extrainfo.modif_pos = p;
1926 extrainfo.modif_len = e - p;
1928 /* Terminate modifier value */
1934 /* Get to selector value */
1935 p += strspn(p, " \t\n");
1938 fprintf(stderr, "Error: no value for selector `%s' on line %d\n",
1939 selector->name, linenum);
1941 break; /* Line ended */
1943 /* Check for quoted arguments */
1951 "Error: unterminated quoted value on line %d\n",
1954 break; /* Line ended */
1961 /* Just end at next blank */
1962 n = strcspn(p, " \t\n");
1965 /* Make 'e' point past the '\0' we are going to add */
1968 /* Terminate selector value */
1971 /* Add it to the mapping */
1972 ret = selector->add_fn(ifnode, selector_active, p, n,
1977 /* Go to next selector */
1979 p += strspn(p, " \t\n");
1982 /* We add a mapping only if it has at least one selector and if all
1983 * selectors were parsed properly. */
1986 /* If we have not yet printed an error, now is a good time ;-) */
1988 fprintf(stderr, "Error: Line %d ignored, no valid selectors\n",
1991 fprintf(stderr, "Error: Line %d ignored due to prior errors\n",
1998 /* Link it in the list */
1999 ifnode->next = mapping_list;
2000 mapping_list = ifnode;
2007 /* Finished reading, close the file */
2013 /*------------------------------------------------------------------*/
2015 * Extract all the interesting selectors for the interface in consideration
2017 static struct if_mapping *
2018 mapping_extract(int skfd,
2019 const char * ifname)
2021 struct if_mapping * target;
2024 /* Create mapping, zero it */
2025 target = calloc(1, sizeof(if_mapping));
2028 fprintf(stderr, "Error: Can't allocate interface mapping.\n");
2032 /* Set the interface name */
2033 strcpy(target->ifname, ifname);
2035 /* Loop on all active selectors */
2036 for(i = 0; i < SELECT_NUM; i++)
2038 /* Check if this selector is active */
2039 if(selector_active[i] != 0)
2041 /* Extract selector */
2042 selector_list[i].get_fn(skfd, ifname, target, selector_active[i]);
2044 /* Ignore errors. Some mapping may not need all selectors */
2051 /*------------------------------------------------------------------*/
2053 * Find the first mapping in the list matching the one we want.
2055 static struct if_mapping *
2056 mapping_find(struct if_mapping * target)
2058 struct if_mapping * ifnode;
2061 /* Look over all our mappings */
2062 for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next)
2066 /* Look over all our selectors, all must match */
2067 for(i = 0; i < SELECT_NUM; i++)
2069 /* Check if this selector is active */
2070 if(ifnode->active[i] != 0)
2072 /* If this selector doesn't match, game over for this mapping */
2073 if((target->active[i] == 0) ||
2074 (selector_list[i].cmp_fn(ifnode, target) != 0))
2082 /* Check is this mapping was "the one" */
2091 /************************** MODULE SUPPORT **************************/
2093 * Load all necessary module so that interfaces do exist.
2094 * This is necessary for system that are fully modular when
2095 * doing the boot time processing, because we need to run before
2099 /*------------------------------------------------------------------*/
2101 * Probe interfaces based on our list of mappings.
2102 * This is the default, but usually not the best way to do it.
2105 probe_mappings(int skfd)
2107 struct if_mapping * ifnode;
2110 /* Look over all our mappings */
2111 for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next)
2113 /* Can't load wildcards interface name :-( */
2114 if(strchr(ifnode->ifname, '%') != NULL)
2118 fprintf(stderr, "Probing : Trying to load interface [%s]\n",
2121 /* Trick the kernel into loading the interface.
2122 * This allow us to not depend on the exact path and
2123 * name of the '/sbin/modprobe' command.
2124 * Obviously, we expect this command to 'fail', as
2125 * the interface will load with the old/wrong name.
2127 strncpy(ifr.ifr_name, ifnode->ifname, IFNAMSIZ);
2128 ioctl(skfd, SIOCGIFHWADDR, &ifr);
2132 /*------------------------------------------------------------------*/
2134 * Probe interfaces based on Debian's config files.
2135 * This allow to enly load modules for interfaces the user want active,
2136 * all built-in interfaces that should remain unconfigured won't
2137 * be probed (and can have mappings).
2140 probe_debian(int skfd)
2143 char * linebuf = NULL;
2147 /* Open Debian config file */
2148 stream = fopen(DEBIAN_CONFIG_FILE, "r");
2151 fprintf(stderr, "Error: can't open file [%s]\n", DEBIAN_CONFIG_FILE);
2155 /* Read each line of file
2156 * getline is a GNU extension :-( The buffer is recycled and increased
2157 * as needed by getline. */
2158 while(getline(&linebuf, &linelen, stream) > 0)
2164 /* Check for auto keyword, ignore when commented out */
2165 if(!strncasecmp(linebuf, "auto ", 5))
2167 /* Skip "auto" keyword */
2170 /* Terminate at first comment */
2175 /* Loop on all interfaces given */
2178 /* Interface name length */
2179 n = strcspn(p, " \t\n");
2181 /* Look for end of interface name */
2183 /* Make 'e' point past the '\0' we are going to add */
2186 /* Terminate interface name */
2190 fprintf(stderr, "Probing : Trying to load interface [%s]\n",
2193 /* Load interface */
2194 strncpy(ifr.ifr_name, p, IFNAMSIZ);
2195 ioctl(skfd, SIOCGIFHWADDR, &ifr);
2197 /* Go to next interface name */
2199 p += strspn(p, " \t\n");
2209 /**************************** MAIN LOGIC ****************************/
2211 /*------------------------------------------------------------------*/
2213 * Rename an interface to a specified new name.
2216 process_rename(int skfd,
2220 char newname[IFNAMSIZ+1];
2221 char retname[IFNAMSIZ+1];
2225 len = strlen(pattern);
2226 star = strchr(pattern, '*');
2228 /* Check newname length, need one extra char for wildcard */
2229 if((len + (star != NULL)) > IFNAMSIZ)
2231 fprintf(stderr, "Error: Interface name `%s' too long.\n",
2236 /* Copy to local buffer */
2237 memcpy(newname, pattern, len + 1);
2239 /* Convert wildcard to the proper format */
2242 /* Replace '*' with '%d' in the new buffer */
2243 star += newname - pattern;
2244 memmove(star + 2, star + 1, len + 1 - (star - newname));
2249 /* Change the name of the interface */
2250 if(if_set_name(skfd, ifname, newname, retname) < 0)
2252 fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
2253 ifname, newname, strerror(errno));
2257 /* Always print out the *new* interface name so that
2258 * the calling script can pick it up and know where its interface
2260 printf("%s\n", retname);
2266 /*------------------------------------------------------------------*/
2268 * Process a specified interface.
2271 process_ifname(int skfd,
2276 struct if_mapping * target;
2277 const struct if_mapping * mapping;
2278 char retname[IFNAMSIZ+1];
2280 /* Avoid "Unused parameter" warning */
2281 args = args; count = count;
2283 /* Get description of this interface */
2284 target = mapping_extract(skfd, ifname);
2288 /* Find matching mapping */
2289 mapping = mapping_find(target);
2293 /* If user specified a new name, keep only interfaces that would
2294 * match the new name... */
2295 if((new_name != NULL) && (if_match_ifname(mapping->ifname, new_name) != 0))
2298 /* Check if user want only dry-run.
2299 * Note that, in the case of wildcard, we don't resolve the wildcard.
2300 * That would be tricky to do... */
2303 printf("Dry-run : Would rename %s to %s.\n",
2304 target->ifname, mapping->ifname);
2308 /* Change the name of the interface */
2309 if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
2311 fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
2312 target->ifname, mapping->ifname, strerror(errno));
2316 /* Check if called with an explicit interface name */
2319 /* Always print out the *new* interface name so that
2320 * the calling script can pick it up and know where its interface
2322 printf("%s\n", retname);
2329 /*------------------------------------------------------------------*/
2331 * Process all network interface present on the system.
2334 process_iflist(int skfd,
2341 iw_enum_devices(skfd, &process_ifname, args, count);
2343 /* If we do any takeover, the interface list grabbed with
2344 * iw_enum_devices() may get out of sync with the real interfaces,
2345 * and we may miss the victim interface. So, let's go through the
2347 * On the other hand, we may have ping pong between two interfaces,
2348 * each claiming the same name, so let's not do it forever...
2349 * Two time should be enough for most configs...
2351 if(force_takeover && num_takeover)
2352 /* Play it again, Sam... */
2353 iw_enum_devices(skfd, &process_ifname, args, count);
2359 /******************************* MAIN *******************************/
2362 /*------------------------------------------------------------------*/
2368 fprintf(stderr, "usage: ifrename [-c configurationfile] [-i ifname] [-p] [-t] [-d] [-D]\n");
2372 /*------------------------------------------------------------------*/
2380 const char * conf_file = DEFAULT_CONF;
2381 char * ifname = NULL;
2387 /* Loop over all command line options */
2390 int c = getopt_long(argc, argv, "c:dDi:n:ptvV", long_opt, NULL);
2421 printf("%-8.16s Wireless-Tools version %d\n", "ifrename", WT_VERSION);
2429 /* Read the specified/default config file, or stdin. */
2430 if(mapping_readfile(conf_file) < 0)
2433 /* Create a channel to the NET kernel. */
2434 if((skfd = iw_sockets_open()) < 0)
2440 /* Check if interface name was specified with -i. */
2443 /* Check is target name specified */
2444 if(new_name != NULL)
2446 /* User want to simply rename an interface to a specified name */
2447 ret = process_rename(skfd, ifname, new_name);
2451 /* Rename only this interface based on mappings
2452 * Mostly used for HotPlug processing (from /etc/hotplug/net.agent).
2453 * Process the network interface specified on the command line,
2454 * and return the new name on stdout.
2457 ret = process_ifname(skfd, ifname, NULL, 0);
2462 /* Load all the necesary modules */
2468 probe_mappings(skfd);
2471 /* Rename all system interfaces
2472 * Mostly used for boot time processing (from init scripts).
2474 ret = process_iflist(skfd, NULL, 0);
2478 iw_sockets_close(skfd);