OSDN Git Service

Update to v30-pre9
[android-x86/external-wireless-tools.git] / wireless_tools / ifrename.c
1 /*
2  *      Wireless Tools
3  *
4  *              Jean II - HPL 04 -> 07
5  *
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".
9  *
10  * This file is released under the GPL license.
11  *     Copyright (c) 2007 Jean Tourrilhes <jt@hpl.hp.com>
12  */
13
14 /* 
15  * The changelog for ifrename is in the file CHANGELOG.h ;-)
16  *
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  * -------------------------------------------------------
26  *
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 and sysfs symlinks...
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)
39  */
40
41 /***************************** INCLUDES *****************************/
42
43 /* This is needed to enable GNU extensions such as getline & FNM_CASEFOLD */
44 #ifndef _GNU_SOURCE 
45 #define _GNU_SOURCE
46 #endif
47
48 #include <getopt.h>             /* getopt_long() */
49 #include <linux/sockios.h>      /* SIOCSIFNAME */
50 #include <fnmatch.h>            /* fnmatch() */
51 //#include <sys/syslog.h>
52
53 #include "iwlib.h"              /* Wireless Tools library */
54
55 // This would be cool, unfortunately...
56 //#include <linux/ethtool.h>    /* Ethtool stuff -> struct ethtool_drvinfo */
57
58 /************************ CONSTANTS & MACROS ************************/
59
60 /* Our default configuration file */
61 const char DEFAULT_CONF[] =             "/etc/iftab"; 
62
63 /* Debian stuff */
64 const char DEBIAN_CONFIG_FILE[] =       "/etc/network/interfaces";
65
66 /* Backward compatibility */
67 #ifndef ifr_newname
68 #define ifr_newname ifr_ifru.ifru_slave
69 #endif
70
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 */
85 const int SELECT_PREVNAME       = 13;   /* Select by previous interface name */
86 #define SELECT_NUM              14
87
88 #define HAS_MAC_EXACT   1
89 #define HAS_MAC_FILTER  2
90 #define MAX_MAC_LEN     16      /* Maximum lenght of MAC address */
91
92 const struct ether_addr zero_mac = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
93
94 const struct option long_opt[] =
95
96   {"config-file", 1, NULL, 'c' },
97   {"debian", 0, NULL, 'd' },
98   {"dry-run", 0, NULL, 'D' },
99   {"help", 0, NULL, '?' },
100   {"interface", 1, NULL, 'i' },
101   {"newname", 1, NULL, 'n' },
102   {"takeover", 0, NULL, 't' },
103   {"udev", 0, NULL, 'u' },
104   {"version", 0, NULL, 'v' },
105   {"verbose", 0, NULL, 'V' },
106   {NULL, 0, NULL, '\0' },
107 };
108
109 /* Pcmcia stab files */
110 #define PCMCIA_STAB1    "/var/lib/pcmcia/stab"
111 #define PCMCIA_STAB2    "/var/run/stab"
112
113 /* Max number of sysfs file types we support */
114 #define SYSFS_MAX_FILE  8
115
116 /* Userspace headers lag, fix that... */
117 #ifndef ARPHRD_IEEE1394
118 #define ARPHRD_IEEE1394 24
119 #endif
120 #ifndef ARPHRD_EUI64
121 #define ARPHRD_EUI64 27
122 #endif
123 #ifndef ARPHRD_IRDA
124 #define ARPHRD_IRDA 783
125 #endif
126
127 /* Length of various non-standard MAC addresses */
128 const int       weird_mac_len[][2] =
129 {
130   { ARPHRD_IEEE1394, 8 },
131   { ARPHRD_EUI64, 8 },
132   { ARPHRD_IRDA, 4 },
133 };
134 const int weird_mac_len_num = sizeof(weird_mac_len) / sizeof(weird_mac_len[0]);
135
136 /****************************** TYPES ******************************/
137
138 /* Cut'n'paste from ethtool.h */
139 #define ETHTOOL_BUSINFO_LEN     32
140 /* these strings are set to whatever the driver author decides... */
141 struct ethtool_drvinfo {
142         __u32   cmd;
143         char    driver[32];     /* driver short name, "tulip", "eepro100" */
144         char    version[32];    /* driver version string */
145         char    fw_version[32]; /* firmware version string, if applicable */
146         char    bus_info[ETHTOOL_BUSINFO_LEN];  /* Bus info for this IF. */
147                                 /* For PCI devices, use pci_dev->slot_name. */
148         char    reserved1[32];
149         char    reserved2[16];
150         __u32   n_stats;        /* number of u64's from ETHTOOL_GSTATS */
151         __u32   testinfo_len;
152         __u32   eedump_len;     /* Size of data from ETHTOOL_GEEPROM (bytes) */
153         __u32   regdump_len;    /* Size of data from ETHTOOL_GREGS (bytes) */
154 };
155 #define ETHTOOL_GDRVINFO        0x00000003 /* Get driver info. */
156
157 /* Description of an interface mapping */
158 typedef struct if_mapping
159
160   /* Linked list */
161   struct if_mapping *   next;
162
163   /* Name of this interface */
164   char                  ifname[IFNAMSIZ+1];
165   char *                sysfs_devpath;
166   int                   sysfs_devplen;
167
168   /* Selectors for this interface */
169   int                   active[SELECT_NUM];     /* Selectors active */
170
171   /* Selector data */
172   unsigned char         mac[MAX_MAC_LEN];       /* Exact MAC address, hex */
173   int                   mac_len;                /* Length (usually 6) */
174   char                  mac_filter[16*3 + 1];   /* WildCard, ascii */
175   unsigned short        hw_type;                /* Link/ARP type */
176   char                  driver[32];             /* driver short name */
177   char          bus_info[ETHTOOL_BUSINFO_LEN];  /* Bus info for this IF. */
178   char                  fw_version[32];         /* Firmware revision */
179   unsigned short        base_addr;              /* HW Base I/O address */ 
180   unsigned char         irq;                    /* HW irq line */
181   char                  iwproto[IFNAMSIZ + 1];  /* Wireless/protocol name */
182   int                   pcmcia_slot;            /* Pcmcia slot */
183   char *                sysfs[SYSFS_MAX_FILE];  /* sysfs selectors */
184   char                  prevname[IFNAMSIZ+1];   /* previous interface name */
185 } if_mapping;
186
187 /* Extra parsing information when adding a mapping */
188 typedef struct add_extra
189
190   char *                modif_pos;              /* Descriptor modifier */
191   size_t                modif_len;
192 } parsing_extra;
193
194 /* Prototype for adding a selector to a mapping. Return -1 if invalid value. */
195 typedef int (*mapping_add)(struct if_mapping *  ifnode,
196                            int *                active,
197                            char *               pos,
198                            size_t               len,
199                            struct add_extra *   extra,
200                            int                  linenum);
201
202 /* Prototype for comparing the selector of two mapping. Return 0 if matches. */
203 typedef int (*mapping_cmp)(struct if_mapping *  ifnode,
204                            struct if_mapping *  target);
205 /* Prototype for extracting selector value from live interface */
206 typedef int (*mapping_get)(int                  skfd,
207                            const char *         ifname,
208                            struct if_mapping *  target,
209                            int                  flag);
210
211 /* How to handle a selector */
212 typedef struct mapping_selector
213 {
214   char *        name;
215   mapping_add   add_fn;
216   mapping_cmp   cmp_fn;
217   mapping_get   get_fn;
218 } mapping_selector;
219
220 /* sysfs global data */
221 typedef struct sysfs_metadata
222 {
223   char *                root;                   /* Root of the sysfs */
224   int                   rlen;                   /* Size of it */
225   int                   filenum;                /* Number of files */
226   char *                filename[SYSFS_MAX_FILE];       /* Name of files */
227 } sysfs_metadata;
228
229 /**************************** PROTOTYPES ****************************/
230
231 static int
232         mapping_addmac(struct if_mapping *      ifnode,
233                        int *                    active,
234                        char *                   pos,
235                        size_t                   len,
236                        struct add_extra *       extra,
237                        int                      linenum);
238 static int
239         mapping_cmpmac(struct if_mapping *      ifnode,
240                        struct if_mapping *      target);
241 static int
242         mapping_getmac(int                      skfd,
243                        const char *             ifname,
244                        struct if_mapping *      target,
245                        int                      flag);
246 static int
247         mapping_addarp(struct if_mapping *      ifnode,
248                        int *                    active,
249                        char *                   pos,
250                        size_t                   len,
251                        struct add_extra *       extra,
252                        int                      linenum);
253 static int
254         mapping_cmparp(struct if_mapping *      ifnode,
255                        struct if_mapping *      target);
256 static int
257         mapping_getarp(int                      skfd,
258                        const char *             ifname,
259                        struct if_mapping *      target,
260                        int                      flag);
261 static int
262         mapping_adddriver(struct if_mapping *   ifnode,
263                           int *                 active,
264                           char *                pos,
265                           size_t                len,
266                           struct add_extra *    extra,
267                           int                   linenum);
268 static int
269         mapping_cmpdriver(struct if_mapping *   ifnode,
270                           struct if_mapping *   target);
271 static int
272         mapping_addbusinfo(struct if_mapping *  ifnode,
273                            int *                active,
274                            char *               pos,
275                            size_t               len,
276                            struct add_extra *   extra,
277                            int                  linenum);
278 static int
279         mapping_cmpbusinfo(struct if_mapping *  ifnode,
280                            struct if_mapping *  target);
281 static int
282         mapping_addfirmware(struct if_mapping * ifnode,
283                             int *               active,
284                             char *              pos,
285                             size_t              len,
286                             struct add_extra *  extra,
287                             int                 linenum);
288 static int
289         mapping_cmpfirmware(struct if_mapping * ifnode,
290                             struct if_mapping * target);
291 static int
292         mapping_getdriverbusinfo(int                    skfd,
293                                  const char *           ifname,
294                                  struct if_mapping *    target,
295                                  int                    flag);
296 static int
297         mapping_addbaseaddr(struct if_mapping * ifnode,
298                             int *               active,
299                             char *              pos,
300                             size_t              len,
301                             struct add_extra *  extra,
302                             int                 linenum);
303 static int
304         mapping_cmpbaseaddr(struct if_mapping * ifnode,
305                             struct if_mapping * target);
306 static int
307         mapping_addirq(struct if_mapping *      ifnode,
308                        int *                    active,
309                        char *                   pos,
310                        size_t                   len,
311                        struct add_extra *       extra,
312                        int                      linenum);
313 static int
314         mapping_cmpirq(struct if_mapping *      ifnode,
315                        struct if_mapping *      target);
316 static int
317         mapping_getbaseaddrirq(int                      skfd,
318                                const char *             ifname,
319                                struct if_mapping *      target,
320                                int                      flag);
321 static int
322         mapping_addiwproto(struct if_mapping *  ifnode,
323                            int *                active,
324                            char *               pos,
325                            size_t               len,
326                            struct add_extra *   extra,
327                            int                  linenum);
328 static int
329         mapping_cmpiwproto(struct if_mapping *  ifnode,
330                            struct if_mapping *  target);
331 static int
332         mapping_getiwproto(int                  skfd,
333                            const char *         ifname,
334                            struct if_mapping *  target,
335                            int                  flag);
336 static int
337         mapping_addpcmciaslot(struct if_mapping *       ifnode,
338                               int *                     active,
339                               char *                    pos,
340                               size_t                    len,
341                               struct add_extra *        extra,
342                               int                       linenum);
343 static int
344         mapping_cmppcmciaslot(struct if_mapping *       ifnode,
345                            struct if_mapping *          target);
346 static int
347         mapping_getpcmciaslot(int                       skfd,
348                               const char *              ifname,
349                               struct if_mapping *       target,
350                               int                       flag);
351 static int
352         mapping_addsysfs(struct if_mapping *    ifnode,
353                          int *                  active,
354                          char *                 pos,
355                          size_t                 len,
356                          struct add_extra *     extra,
357                          int                    linenum);
358 static int
359         mapping_cmpsysfs(struct if_mapping *    ifnode,
360                          struct if_mapping *    target);
361 static int
362         mapping_getsysfs(int                    skfd,
363                          const char *           ifname,
364                          struct if_mapping *    target,
365                          int                    flag);
366 static int
367         mapping_addprevname(struct if_mapping * ifnode,
368                            int *                active,
369                            char *               pos,
370                            size_t               len,
371                            struct add_extra *   extra,
372                            int                  linenum);
373 static int
374         mapping_cmpprevname(struct if_mapping * ifnode,
375                            struct if_mapping *  target);
376 static int
377         mapping_getprevname(int                 skfd,
378                            const char *         ifname,
379                            struct if_mapping *  target,
380                            int                  flag);
381
382 /**************************** VARIABLES ****************************/
383
384 /* List of mapping read for config file */
385 struct if_mapping *     mapping_list = NULL;
386
387 /* List of selectors we can handle */
388 const struct mapping_selector   selector_list[] =
389 {
390   /* MAC address and ARP/Link type from ifconfig */
391   { "mac", &mapping_addmac, &mapping_cmpmac, &mapping_getmac },
392   { "ethaddr", &mapping_addmac, &mapping_cmpmac, &mapping_getmac },
393   { "arp", &mapping_addarp, &mapping_cmparp, &mapping_getarp },
394   { "linktype", &mapping_addarp, &mapping_cmparp, &mapping_getarp },
395   /* Driver name, Bus-Info and firmware rev from ethtool -i */
396   { "driver", &mapping_adddriver, &mapping_cmpdriver,
397     &mapping_getdriverbusinfo },
398   { "businfo", &mapping_addbusinfo, &mapping_cmpbusinfo,
399     &mapping_getdriverbusinfo },
400   { "firmware", &mapping_addfirmware, &mapping_cmpfirmware,
401     &mapping_getdriverbusinfo },
402   /* Base Address and IRQ from ifconfig */
403   { "baseaddress", &mapping_addbaseaddr, &mapping_cmpbaseaddr,
404     &mapping_getbaseaddrirq },
405   { "irq", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq },
406   { "interrupt", &mapping_addirq, &mapping_cmpirq, &mapping_getbaseaddrirq },
407   /* Wireless Protocol from iwconfig */
408   { "iwproto", &mapping_addiwproto, &mapping_cmpiwproto, &mapping_getiwproto },
409   /* Pcmcia slot from cardmgr */
410   { "pcmciaslot", &mapping_addpcmciaslot, &mapping_cmppcmciaslot, &mapping_getpcmciaslot },
411   /* sysfs file (udev emulation) */
412   { "sysfs", &mapping_addsysfs, &mapping_cmpsysfs, &mapping_getsysfs },
413   /* previous interface name */
414   { "prevname", &mapping_addprevname, &mapping_cmpprevname, &mapping_getprevname },
415   /* The Terminator */
416   { NULL, NULL, NULL, NULL },
417 };
418 const int selector_num = sizeof(selector_list)/sizeof(selector_list[0]);
419
420 /* List of active selectors */
421 int     selector_active[SELECT_NUM];    /* Selectors active */
422
423 /*
424  * All the following flags are controlled by the command line switches...
425  * It's a bit hackish to have them all as global, so maybe we should pass
426  * them in a big struct as function arguments... More complex and
427  * probably not worth it ?
428  */
429
430 /* Invocation type */
431 int     print_newname = 0;
432 char *  new_name = NULL;
433
434 /* Takeover support */
435 int     force_takeover = 0;     /* Takeover name from other interfaces */
436 int     num_takeover = 0;       /* Number of takeover done */
437
438 /* Number of mapping matched */
439 int     num_mapping_match = 0;
440
441 /* Dry-run support */
442 int     dry_run = 0;            /* Just print new name, don't rename */
443
444 /* Verbose support (i.e. debugging) */
445 int     verbose = 0;
446
447 /* udev output support (print new DEVPATH) */
448 int     udev_output = 0;
449
450 /* sysfs global data */
451 struct sysfs_metadata   sysfs_global =
452 {
453   NULL, 0,
454   0, { NULL, NULL, NULL, NULL, NULL },
455 };
456
457 /******************** INTERFACE NAME MANAGEMENT ********************/
458 /*
459  * Bunch of low level function for managing interface names.
460  */
461
462 /*------------------------------------------------------------------*/
463 /*
464  * Compare two interface names, with wildcards.
465  * We can't use fnmatch() because we don't want expansion of '[...]'
466  * expressions, '\' sequences and matching of '.'.
467  * We only want to match a single '*' (converted to a %d at that point)
468  * to a numerical value (no ascii).
469  * Return 0 is matches.
470  */
471 static int
472 if_match_ifname(const char *    pattern,
473                 const char *    value)
474 {
475   const char *  p;
476   const char *  v;
477   int           n;
478   int           ret;
479
480   /* Check for a wildcard */
481   p = strchr(pattern, '*');
482
483   /* No wildcard, simple comparison */
484   if(p == NULL)
485     return(strcmp(pattern, value));
486
487   /* Check is prefixes match */
488   n = (p - pattern);
489   ret = strncmp(pattern, value, n);
490   if(ret)
491     return(ret);
492
493   /* Check that value has some digits at this point */
494   v = value + n;
495   if(!isdigit(*v))
496     return(-1);
497
498   /* Skip digits to go to value suffix */
499   do
500     v++;
501   while(isdigit(*v));
502
503   /* Pattern suffix */
504   p += 1;
505
506   /* Compare suffixes */
507   return(strcmp(p, v));
508 }
509
510 /*------------------------------------------------------------------*/
511 /*
512  * Steal interface name from another interface. This enable interface
513  * name swapping.
514  * This will work :
515  *      1) with kernel 2.6.X
516  *      2) if other interface is down
517  * Because of (2), it won't work with hotplug, but we don't need it
518  * with hotplug, only with static ifaces...
519  */
520 static int
521 if_takeover_name(int                    skfd,
522                  const char *           victimname)
523 {
524   char          autoname[IFNAMSIZ+1];
525   int           len;
526   struct ifreq  ifr;
527   int           ret;
528
529   /* Compute name for victim interface */
530   len = strlen(victimname);
531   memcpy(autoname, victimname, len + 1);
532   if(len > (IFNAMSIZ - 2))
533     len = IFNAMSIZ - 2;         /* Make sure we have at least two char */
534   len--;                        /* Convert to index */
535   while(isdigit(autoname[len]))
536     len--;                      /* Scrap all trailing digits */
537   strcpy(autoname + len + 1, "%d");
538
539   if(verbose)
540     fprintf(stderr, "Takeover : moving interface `%s' to `%s'.\n",
541             victimname, autoname);
542
543   /* Prepare request */
544   bzero(&ifr, sizeof(struct ifreq));
545   strncpy(ifr.ifr_name, victimname, IFNAMSIZ); 
546   strncpy(ifr.ifr_newname, autoname, IFNAMSIZ); 
547
548   /* Rename victim interface */
549   ret = ioctl(skfd, SIOCSIFNAME, &ifr);
550
551   if(!ret)
552     num_takeover++;
553
554   return(ret);
555 }
556
557 /*------------------------------------------------------------------*/
558 /*
559  * Ask the kernel to change the name of an interface.
560  * That's what we want to do. All the rest is to make sure we call this
561  * appropriately.
562  */
563 static int
564 if_set_name(int                 skfd,
565             const char *        oldname,
566             const char *        newname,
567             char *              retname)
568 {
569   struct ifreq  ifr;
570   char *        star;
571   int           ret;
572
573   /* The kernel doesn't check is the interface already has the correct
574    * name and may return an error, so check ourselves.
575    * In the case of wildcard, the result can be weird : if oldname='eth0'
576    * and newname='eth*', retname would be 'eth1'.
577    * So, if the oldname value matches the newname pattern, just return
578    * success. */
579   if(!if_match_ifname(newname, oldname))
580     {
581       if(verbose)
582         fprintf(stderr, "Setting : Interface `%s' already matches `%s'.\n",
583                 oldname, newname);
584
585       strcpy(retname, oldname);
586       return(0);
587     }
588
589   /* Prepare request */
590   bzero(&ifr, sizeof(struct ifreq));
591   strncpy(ifr.ifr_name, oldname, IFNAMSIZ); 
592   strncpy(ifr.ifr_newname, newname, IFNAMSIZ); 
593
594   /* Check for wildcard interface name, such as 'eth*' or 'wlan*'...
595    * This require specific kernel support (2.6.2-rc1 and later).
596    * We externally use '*', but the kernel doesn't know about that,
597    * so convert it to something it knows about... */
598   star = strchr(newname, '*');
599   if(star != NULL)
600     {
601       int       slen = star - newname;
602       /* Replace '*' with '%d' in the new buffer */
603       star = ifr.ifr_newname + slen;
604       /* Size was checked in process_rename() and mapping_create() */
605       memmove(star + 2, star + 1, IFNAMSIZ - slen - 2);
606       star[0] = '%';
607       star[1] = 'd';
608     }
609
610   /* Do it */
611   ret = ioctl(skfd, SIOCSIFNAME, &ifr);
612
613   /* Takeover support : grab interface name from another interface */
614   if(ret && (errno == EEXIST) && force_takeover)
615     {
616       /* Push things around */
617       ret = if_takeover_name(skfd, newname);
618       if(!ret)
619         /* Second try */
620         ret = ioctl(skfd, SIOCSIFNAME, &ifr);
621     }
622
623   if(!ret)
624     {
625       /* Get the real new name (in case newname is a wildcard) */
626       strcpy(retname, ifr.ifr_newname);
627
628       if(verbose)
629         fprintf(stderr, "Setting : Interface `%s' renamed to `%s'.\n",
630                 oldname, retname);
631     }
632
633   return(ret);
634 }
635
636 /************************ SELECTOR HANDLING ************************/
637 /*
638  * Handle the various selector we support
639  */
640
641 /*------------------------------------------------------------------*/
642 /*
643  * Add a MAC address selector to a mapping
644  */
645 static int
646 mapping_addmac(struct if_mapping *      ifnode,
647                int *                    active,
648                char *                   string,
649                size_t                   len,
650                struct add_extra *       extra,
651                int                      linenum)
652 {
653   size_t        n;
654
655   /* Avoid "Unused parameter" warning */
656   extra = extra;
657
658   /* Verify validity of string */
659   if(len >= sizeof(ifnode->mac_filter))
660     { 
661       fprintf(stderr, "Error : MAC address too long at line %d\n", linenum);  
662       return(-1);
663     }
664   n = strspn(string, "0123456789ABCDEFabcdef:*"); 
665   if(n < len)
666     {
667       fprintf(stderr, "Error: Invalid MAC address `%s' at line %d\n",
668               string, linenum);
669       return(-1);
670     }
671
672   /* Copy as filter in all cases */
673   memcpy(ifnode->mac_filter, string, len + 1); 
674
675   /* Check the type of MAC address */
676   if (strchr(ifnode->mac_filter, '*') != NULL)
677     {
678       /* This is a wilcard. Usual format : "01:23:45:*"
679        * Unfortunately, we can't do proper parsing. */
680       ifnode->active[SELECT_MAC] = HAS_MAC_FILTER;
681       active[SELECT_MAC] = HAS_MAC_FILTER;
682     }
683   else
684     {
685       /* Not a wildcard : "01:23:45:67:89:AB" */
686       ifnode->mac_len = iw_mac_aton(ifnode->mac_filter,
687                                     ifnode->mac, MAX_MAC_LEN);
688       if(ifnode->mac_len == 0)
689         {
690           fprintf(stderr, "Error: Invalid MAC address `%s' at line %d\n",
691                   ifnode->mac_filter, linenum);
692           return(-1);
693         }
694
695       /* Check that it's not NULL */
696       if((ifnode->mac_len == 6) && (!memcmp(&ifnode->mac, &zero_mac, 6)))
697         {
698           fprintf(stderr,
699                   "Warning: MAC address is null at line %d, this is dangerous...\n",
700                   linenum);
701         }
702
703       ifnode->active[SELECT_MAC] = HAS_MAC_EXACT;
704       if(active[SELECT_MAC] == 0)
705         active[SELECT_MAC] = HAS_MAC_EXACT;
706     }
707
708   if(verbose)
709     fprintf(stderr,
710             "Parsing : Added %s MAC address `%s' from line %d.\n",
711             ifnode->active[SELECT_MAC] == HAS_MAC_FILTER ? "filter" : "exact",
712             ifnode->mac_filter, linenum);
713
714   return(0);
715 }
716
717 /*------------------------------------------------------------------*/
718 /*
719  * Compare the mac address of two mappings
720  */
721 static int
722 mapping_cmpmac(struct if_mapping *      ifnode,
723                struct if_mapping *      target)
724 {
725   /* Check for wildcard matching */
726   if(ifnode->active[SELECT_MAC] == HAS_MAC_FILTER)
727     /* Do wildcard matching, case insensitive */
728     return(fnmatch(ifnode->mac_filter, target->mac_filter, FNM_CASEFOLD));
729   else
730     /* Exact matching, in hex */
731     return((ifnode->mac_len != target->mac_len) ||
732            memcmp(ifnode->mac, target->mac, ifnode->mac_len));
733 }
734
735 /*------------------------------------------------------------------*/
736 /*
737  * Extract the MAC address and Link Type of an interface
738  */
739 static int
740 mapping_getmac(int                      skfd,
741                const char *             ifname,
742                struct if_mapping *      target,
743                int                      flag)
744 {
745   struct ifreq  ifr;
746   int           ret;
747   int           i;
748
749   /* Get MAC address */
750   bzero(&ifr, sizeof(struct ifreq));
751   strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
752   ret = ioctl(skfd, SIOCGIFHWADDR, &ifr);
753   if(ret < 0)
754     {
755       fprintf(stderr, "Error: Can't read MAC address on interface `%s' : %s\n",
756               ifname, strerror(errno));
757       return(-1);
758     }
759
760   /* Extract ARP type */
761   target->hw_type = ifr.ifr_hwaddr.sa_family;
762   /* Calculate address length */
763   target->mac_len = 6;
764   for(i = 0; i < weird_mac_len_num; i++)
765     if(weird_mac_len[i][0] == ifr.ifr_hwaddr.sa_family)
766       {
767         target->mac_len = weird_mac_len[i][1];
768         break;
769       }
770   /* Extract MAC address bytes */
771   memcpy(target->mac, ifr.ifr_hwaddr.sa_data, target->mac_len);
772
773   /* Check the type of comparison */
774   if((flag == HAS_MAC_FILTER) || verbose)
775     {
776       /* Convert to ASCII */
777       iw_mac_ntop(target->mac, target->mac_len,
778                   target->mac_filter, sizeof(target->mac_filter));
779     }
780
781   target->active[SELECT_MAC] = flag;
782   target->active[SELECT_ARP] = 1;
783
784   if(verbose)
785     fprintf(stderr,
786             "Querying %s : Got MAC address `%s' and ARP/Link Type `%d'.\n",
787             ifname, target->mac_filter, target->hw_type);
788
789   return(0);
790 }
791
792 /*------------------------------------------------------------------*/
793 /*
794  * Add a ARP/Link type selector to a mapping
795  */
796 static int
797 mapping_addarp(struct if_mapping *      ifnode,
798                int *                    active,
799                char *                   string,
800                size_t                   len,
801                struct add_extra *       extra,
802                int                      linenum)
803 {
804   size_t        n;
805   unsigned int  type;
806
807   /* Avoid "Unused parameter" warning */
808   extra = extra;
809
810   /* Verify validity of string, convert to int */
811   n = strspn(string, "0123456789"); 
812   if((n < len) || (sscanf(string, "%d", &type) != 1))
813     {
814       fprintf(stderr, "Error: Invalid ARP/Link Type `%s' at line %d\n",
815               string, linenum);
816       return(-1);
817     }
818
819   ifnode->hw_type = (unsigned short) type;
820   ifnode->active[SELECT_ARP] = 1;
821   active[SELECT_ARP] = 1;
822
823   if(verbose)
824     fprintf(stderr, "Parsing : Added ARP/Link Type `%d' from line %d.\n",
825             ifnode->hw_type, linenum);
826
827   return(0);
828 }
829
830 /*------------------------------------------------------------------*/
831 /*
832  * Compare the ARP/Link type of two mappings
833  */
834 static int
835 mapping_cmparp(struct if_mapping *      ifnode,
836                struct if_mapping *      target)
837 {
838   return(!(ifnode->hw_type == target->hw_type));
839 }
840
841 /*------------------------------------------------------------------*/
842 /*
843  * Extract the ARP/Link type of an interface
844  */
845 static int
846 mapping_getarp(int                      skfd,
847                const char *             ifname,
848                struct if_mapping *      target,
849                int                      flag)
850 {
851   /* We may have already extracted the MAC address */
852   if(target->active[SELECT_MAC])
853     return(0);
854
855   /* Otherwise just do it */
856   return(mapping_getmac(skfd, ifname, target, flag));
857 }
858
859 /*------------------------------------------------------------------*/
860 /*
861  * Add a Driver name selector to a mapping
862  */
863 static int
864 mapping_adddriver(struct if_mapping *   ifnode,
865                   int *                 active,
866                   char *                string,
867                   size_t                len,
868                   struct add_extra *    extra,
869                   int                   linenum)
870 {
871   /* Avoid "Unused parameter" warning */
872   extra = extra;
873
874   /* Plain string, minimal verification */
875   if(len >= sizeof(ifnode->driver))
876     { 
877       fprintf(stderr, "Error: Driver name too long at line %d\n", linenum);  
878       return(-1);
879     }
880
881   /* Copy */
882   memcpy(ifnode->driver, string, len + 1); 
883
884   /* Activate */
885   ifnode->active[SELECT_DRIVER] = 1;
886   active[SELECT_DRIVER] = 1;
887
888   if(verbose)
889     fprintf(stderr,
890             "Parsing : Added Driver name `%s' from line %d.\n",
891             ifnode->driver, linenum);
892
893   return(0);
894 }
895
896 /*------------------------------------------------------------------*/
897 /*
898  * Compare the Driver name of two mappings
899  */
900 static int
901 mapping_cmpdriver(struct if_mapping *   ifnode,
902                   struct if_mapping *   target)
903 {
904   /* Do wildcard matching, case insensitive */
905   return(fnmatch(ifnode->driver, target->driver, FNM_CASEFOLD));
906 }
907
908 /*------------------------------------------------------------------*/
909 /*
910  * Add a Bus-Info selector to a mapping
911  */
912 static int
913 mapping_addbusinfo(struct if_mapping *  ifnode,
914                    int *                active,
915                    char *               string,
916                    size_t               len,
917                    struct add_extra *   extra,
918                    int                  linenum)
919 {
920 #if 0
921   size_t        n;
922 #endif
923
924   /* Avoid "Unused parameter" warning */
925   extra = extra;
926
927   /* Verify validity of string */
928   if(len >= sizeof(ifnode->bus_info))
929     { 
930       fprintf(stderr, "Bus Info too long at line %d\n", linenum);  
931       return(-1);
932     }
933 #if 0
934   /* Hum... This doesn's seem true for non-PCI bus-info */
935   n = strspn(string, "0123456789ABCDEFabcdef:.*"); 
936   if(n < len)
937     {
938       fprintf(stderr, "Error: Invalid Bus Info `%s' at line %d\n",
939               string, linenum);
940       return(-1);
941     }
942 #endif
943
944   /* Copy */
945   memcpy(ifnode->bus_info, string, len + 1); 
946
947   /* Activate */
948   ifnode->active[SELECT_BUSINFO] = 1;
949   active[SELECT_BUSINFO] = 1;
950
951   if(verbose)
952     fprintf(stderr,
953             "Parsing : Added Bus Info `%s' from line %d.\n",
954             ifnode->bus_info, linenum);
955
956   return(0);
957 }
958
959 /*------------------------------------------------------------------*/
960 /*
961  * Compare the Bus-Info of two mappings
962  */
963 static int
964 mapping_cmpbusinfo(struct if_mapping *  ifnode,
965                    struct if_mapping *  target)
966 {
967   /* Do wildcard matching, case insensitive */
968   return(fnmatch(ifnode->bus_info, target->bus_info, FNM_CASEFOLD));
969 }
970
971 /*------------------------------------------------------------------*/
972 /*
973  * Add a Firmare revision selector to a mapping
974  */
975 static int
976 mapping_addfirmware(struct if_mapping * ifnode,
977                     int *               active,
978                     char *              string,
979                     size_t              len,
980                     struct add_extra *  extra,
981                     int                 linenum)
982 {
983   /* Avoid "Unused parameter" warning */
984   extra = extra;
985
986   /* Verify validity of string */
987   if(len >= sizeof(ifnode->fw_version))
988     { 
989       fprintf(stderr, "Firmware revision too long at line %d\n", linenum);  
990       return(-1);
991     }
992
993   /* Copy */
994   memcpy(ifnode->fw_version, string, len + 1); 
995
996   /* Activate */
997   ifnode->active[SELECT_FIRMWARE] = 1;
998   active[SELECT_FIRMWARE] = 1;
999
1000   if(verbose)
1001     fprintf(stderr,
1002             "Parsing : Added Firmware Revision `%s' from line %d.\n",
1003             ifnode->fw_version, linenum);
1004
1005   return(0);
1006 }
1007
1008 /*------------------------------------------------------------------*/
1009 /*
1010  * Compare the Bus-Info of two mappings
1011  */
1012 static int
1013 mapping_cmpfirmware(struct if_mapping * ifnode,
1014                     struct if_mapping * target)
1015 {
1016   /* Do wildcard matching, case insensitive */
1017   return(fnmatch(ifnode->fw_version, target->fw_version, FNM_CASEFOLD));
1018 }
1019
1020 /*------------------------------------------------------------------*/
1021 /*
1022  * Extract the Driver name and Bus-Info from a live interface
1023  */
1024 static int
1025 mapping_getdriverbusinfo(int                    skfd,
1026                          const char *           ifname,
1027                          struct if_mapping *    target,
1028                          int                    flag)
1029 {
1030   struct ifreq  ifr;
1031   struct ethtool_drvinfo drvinfo;
1032   int   ret;
1033
1034   /* Avoid "Unused parameter" warning */
1035   flag = flag;
1036
1037   /* We may come here twice or more, so do the job only once */
1038   if(target->active[SELECT_DRIVER] || target->active[SELECT_BUSINFO]
1039      || target->active[SELECT_FIRMWARE])
1040     return(0);
1041
1042   /* Prepare request */
1043   bzero(&ifr, sizeof(struct ifreq));
1044   bzero(&drvinfo, sizeof(struct ethtool_drvinfo));
1045   strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1046   drvinfo.cmd = ETHTOOL_GDRVINFO;
1047   ifr.ifr_data = (caddr_t) &drvinfo;
1048
1049   /* Do it */
1050   ret = ioctl(skfd, SIOCETHTOOL, &ifr);
1051   if(ret < 0)
1052     {
1053       /* Most drivers don't support that, keep quiet for now */
1054       if(verbose)
1055         fprintf(stderr,
1056                 "Error: Can't read driver/bus-info on interface `%s' : %s\n",
1057                 ifname, strerror(errno));
1058       return(-1);
1059     }
1060
1061   /* Copy over */
1062   strcpy(target->driver, drvinfo.driver);
1063   strcpy(target->bus_info, drvinfo.bus_info);
1064   strcpy(target->fw_version, drvinfo.fw_version);
1065
1066   /* Activate */
1067   target->active[SELECT_DRIVER] = 1;
1068   target->active[SELECT_BUSINFO] = 1;
1069   target->active[SELECT_FIRMWARE] = 1;
1070
1071   if(verbose)
1072     fprintf(stderr,
1073             "Querying %s : Got Driver name `%s', Bus Info `%s' and Firmware `%s'.\n",
1074             ifname, target->driver, target->bus_info, target->fw_version);
1075
1076   return(0);
1077 }
1078
1079 /*------------------------------------------------------------------*/
1080 /*
1081  * Add a Base Address selector to a mapping
1082  */
1083 static int
1084 mapping_addbaseaddr(struct if_mapping * ifnode,
1085                     int *               active,
1086                     char *              string,
1087                     size_t              len,
1088                     struct add_extra *  extra,
1089                     int                 linenum)
1090 {
1091   size_t        n;
1092   unsigned int  address;
1093
1094   /* Avoid "Unused parameter" warning */
1095   extra = extra;
1096
1097   /* Verify validity of string */
1098   n = strspn(string, "0123456789ABCDEFabcdefx"); 
1099   if((n < len) || (sscanf(string, "0x%X", &address) != 1))
1100     {
1101       fprintf(stderr, "Error: Invalid Base Address `%s' at line %d\n",
1102               string, linenum);
1103       return(-1);
1104     }
1105
1106   /* Copy */
1107   ifnode->base_addr = (unsigned short) address;
1108
1109   /* Activate */
1110   ifnode->active[SELECT_BASEADDR] = 1;
1111   active[SELECT_BASEADDR] = 1;
1112
1113   if(verbose)
1114     fprintf(stderr,
1115             "Parsing : Added Base Address `0x%X' from line %d.\n",
1116             ifnode->base_addr, linenum);
1117
1118   return(0);
1119 }
1120
1121 /*------------------------------------------------------------------*/
1122 /*
1123  * Compare the Base Address of two mappings
1124  */
1125 static int
1126 mapping_cmpbaseaddr(struct if_mapping * ifnode,
1127                     struct if_mapping * target)
1128 {
1129   /* Do wildcard matching, case insensitive */
1130   return(!(ifnode->base_addr == target->base_addr));
1131 }
1132
1133 /*------------------------------------------------------------------*/
1134 /*
1135  * Add a IRQ selector to a mapping
1136  */
1137 static int
1138 mapping_addirq(struct if_mapping *      ifnode,
1139                int *                    active,
1140                char *                   string,
1141                size_t                   len,
1142                struct add_extra *       extra,
1143                int                      linenum)
1144 {
1145   size_t        n;
1146   unsigned int  irq;
1147
1148   /* Avoid "Unused parameter" warning */
1149   extra = extra;
1150
1151   /* Verify validity of string */
1152   n = strspn(string, "0123456789"); 
1153   if((n < len) || (sscanf(string, "%d", &irq) != 1))
1154     {
1155       fprintf(stderr, "Error: Invalid Base Address `%s' at line %d\n",
1156               string, linenum);
1157       return(-1);
1158     }
1159
1160   /* Copy */
1161   ifnode->irq = (unsigned char) irq;
1162
1163   /* Activate */
1164   ifnode->active[SELECT_IRQ] = 1;
1165   active[SELECT_IRQ] = 1;
1166
1167   if(verbose)
1168     fprintf(stderr,
1169             "Parsing : Added IRQ `%d' from line %d.\n",
1170             ifnode->irq, linenum);
1171
1172   return(0);
1173 }
1174
1175 /*------------------------------------------------------------------*/
1176 /*
1177  * Compare the IRQ of two mappings
1178  */
1179 static int
1180 mapping_cmpirq(struct if_mapping *      ifnode,
1181                struct if_mapping *      target)
1182 {
1183   /* Do wildcard matching, case insensitive */
1184   return(!(ifnode->irq == target->irq));
1185 }
1186
1187 /*------------------------------------------------------------------*/
1188 /*
1189  * Extract the Driver name and Bus-Info from a live interface
1190  */
1191 static int
1192 mapping_getbaseaddrirq(int                      skfd,
1193                        const char *             ifname,
1194                        struct if_mapping *      target,
1195                        int                      flag)
1196 {
1197   struct ifreq  ifr;
1198   struct ifmap  map;            /* hardware setup        */
1199   int   ret;
1200
1201   /* Avoid "Unused parameter" warning */
1202   flag = flag;
1203
1204   /* We may come here twice, so do the job only once */
1205   if(target->active[SELECT_BASEADDR] || target->active[SELECT_IRQ])
1206     return(0);
1207
1208   /* Prepare request */
1209   bzero(&ifr, sizeof(struct ifreq));
1210   bzero(&map, sizeof(struct ifmap));
1211   strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
1212
1213   /* Do it */
1214   ret = ioctl(skfd, SIOCGIFMAP, &ifr);
1215   if(ret < 0)
1216     {
1217       /* Don't know if every interface has that, so keep quiet... */
1218       if(verbose)
1219         fprintf(stderr,
1220                 "Error: Can't read base address/irq on interface `%s' : %s\n",
1221                 ifname, strerror(errno));
1222       return(-1);
1223     }
1224
1225   /* Copy over, activate */
1226   if(ifr.ifr_map.base_addr >= 0x100)
1227     {
1228       target->base_addr = ifr.ifr_map.base_addr;
1229       target->active[SELECT_BASEADDR] = 1;
1230     }
1231   target->irq = ifr.ifr_map.irq;
1232   target->active[SELECT_IRQ] = 1;
1233
1234   if(verbose)
1235     fprintf(stderr,
1236             "Querying %s : Got Base Address `0x%X' and IRQ `%d'.\n",
1237             ifname, target->base_addr, target->irq);
1238
1239   return(0);
1240 }
1241
1242 /*------------------------------------------------------------------*/
1243 /*
1244  * Add a Wireless Protocol selector to a mapping
1245  */
1246 static int
1247 mapping_addiwproto(struct if_mapping *  ifnode,
1248                    int *                active,
1249                    char *               string,
1250                    size_t               len,
1251                    struct add_extra *   extra,
1252                    int                  linenum)
1253 {
1254   /* Avoid "Unused parameter" warning */
1255   extra = extra;
1256
1257   /* Verify validity of string */
1258   if(len >= sizeof(ifnode->iwproto))
1259     { 
1260       fprintf(stderr, "Wireless Protocol too long at line %d\n", linenum);  
1261       return(-1);
1262     }
1263
1264   /* Copy */
1265   memcpy(ifnode->iwproto, string, len + 1); 
1266
1267   /* Activate */
1268   ifnode->active[SELECT_IWPROTO] = 1;
1269   active[SELECT_IWPROTO] = 1;
1270
1271   if(verbose)
1272     fprintf(stderr,
1273             "Parsing : Added Wireless Protocol `%s' from line %d.\n",
1274             ifnode->iwproto, linenum);
1275
1276   return(0);
1277 }
1278
1279 /*------------------------------------------------------------------*/
1280 /*
1281  * Compare the Wireless Protocol of two mappings
1282  */
1283 static int
1284 mapping_cmpiwproto(struct if_mapping *  ifnode,
1285                    struct if_mapping *  target)
1286 {
1287   /* Do wildcard matching, case insensitive */
1288   return(fnmatch(ifnode->iwproto, target->iwproto, FNM_CASEFOLD));
1289 }
1290
1291 /*------------------------------------------------------------------*/
1292 /*
1293  * Extract the Wireless Protocol from a live interface
1294  */
1295 static int
1296 mapping_getiwproto(int                  skfd,
1297                    const char *         ifname,
1298                    struct if_mapping *  target,
1299                    int                  flag)
1300 {
1301   struct iwreq          wrq;
1302
1303   /* Avoid "Unused parameter" warning */
1304   flag = flag;
1305
1306   /* Get wireless name */
1307   if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0)
1308     /* Don't complain about it, Ethernet cards will never support this */
1309     return(-1);
1310
1311   strncpy(target->iwproto, wrq.u.name, IFNAMSIZ);
1312   target->iwproto[IFNAMSIZ] = '\0';
1313
1314   /* Activate */
1315   target->active[SELECT_IWPROTO] = 1;
1316
1317   if(verbose)
1318     fprintf(stderr,
1319             "Querying %s : Got Wireless Protocol `%s'.\n",
1320             ifname, target->iwproto);
1321
1322   return(0);
1323 }
1324
1325 /*------------------------------------------------------------------*/
1326 /*
1327  * Add a Pcmcia Slot selector to a mapping
1328  */
1329 static int
1330 mapping_addpcmciaslot(struct if_mapping *       ifnode,
1331                       int *                     active,
1332                       char *                    string,
1333                       size_t                    len,
1334                       struct add_extra *        extra,
1335                       int                       linenum)
1336 {
1337   size_t        n;
1338
1339   /* Avoid "Unused parameter" warning */
1340   extra = extra;
1341
1342   /* Verify validity of string, convert to int */
1343   n = strspn(string, "0123456789"); 
1344   if((n < len) || (sscanf(string, "%d", &ifnode->pcmcia_slot) != 1))
1345     {
1346       fprintf(stderr, "Error: Invalid Pcmcia Slot `%s' at line %d\n",
1347               string, linenum);
1348       return(-1);
1349     }
1350
1351   ifnode->active[SELECT_PCMCIASLOT] = 1;
1352   active[SELECT_PCMCIASLOT] = 1;
1353
1354   if(verbose)
1355     fprintf(stderr, "Parsing : Added Pcmcia Slot `%d' from line %d.\n",
1356             ifnode->pcmcia_slot, linenum);
1357
1358   return(0);
1359 }
1360
1361 /*------------------------------------------------------------------*/
1362 /*
1363  * Compare the Pcmcia Slot of two mappings
1364  */
1365 static int
1366 mapping_cmppcmciaslot(struct if_mapping *       ifnode,
1367                       struct if_mapping *       target)
1368 {
1369   return(!(ifnode->pcmcia_slot == target->pcmcia_slot));
1370 }
1371
1372 /*------------------------------------------------------------------*/
1373 /*
1374  * Extract the Pcmcia Slot of an interface
1375  * Note that this works only for cards fully managed by cardmgr.
1376  * With the kernel pcmcia modules, 32 bits cards (CardBus) are not managed
1377  * by cardmgr, and therefore won't have a valid slot number. For those
1378  * cards, you should use Bus Info (when the driver exports it).
1379  * In the long term, 16 bits card as well will no longer be managed by
1380  * cardmgr. Currently, Bus Info for 16 bit cards don't have any information
1381  * enabling to locate their physical location on the system, but I hope that
1382  * this will change.
1383  * When that happen, we can drop this code...
1384  */
1385 static int
1386 mapping_getpcmciaslot(int                       skfd,
1387                       const char *              ifname,
1388                       struct if_mapping *       target,
1389                       int                       flag)
1390 {
1391   FILE *        stream;
1392   char *        linebuf = NULL;
1393   size_t        linelen = 0; 
1394   int           linenum = 0; 
1395
1396   /* Avoid "Unused parameter" warning */
1397   skfd = skfd;
1398   flag = flag;
1399
1400   /* Open the stab file for reading */
1401   stream = fopen(PCMCIA_STAB1, "r");
1402   if(!stream) 
1403     {
1404       /* Try again, alternate location */
1405       stream = fopen(PCMCIA_STAB2, "r");
1406       if(!stream) 
1407         {
1408           fprintf(stderr, "Error: Can't open PCMCIA Stab file `%s' or `%s': %s\n",
1409                   PCMCIA_STAB1, PCMCIA_STAB2, strerror(errno)); 
1410           return(-1);
1411         }
1412     }
1413
1414   /* Read each line of file
1415    * getline is a GNU extension :-( The buffer is recycled and increased
1416    * as needed by getline. */
1417   while(getline(&linebuf, &linelen, stream) > 0)
1418     {
1419       char *                    p;
1420       size_t                    n;
1421       size_t                    k;
1422       int                       pcmcia_slot;
1423       int                       i;
1424
1425       /* Keep track of line number */
1426       linenum++;
1427
1428       /* Get Pcmcia socket number */
1429       p = linebuf;
1430       while(isspace(*p))
1431         ++p; 
1432       if(*p == '\0')
1433         continue;       /* Line ended */
1434       n = strcspn(p, " \t\n");
1435       k = strspn(p, "0123456789"); 
1436       if((k < n) || (sscanf(p, "%d", &pcmcia_slot) != 1))
1437         /* Next line */
1438         continue;
1439
1440       /* Skip socket number */
1441       /* Skip socket number ; device class ; driver name ; instance */
1442       for(i = 0; i < 4; i++)
1443         {
1444           /* Skip item */
1445           p += n;
1446           /* Skip space */
1447           p += strspn(p, " \t\n"); 
1448           if(*p == '\0')
1449             break;      /* Line ended */
1450           /* Next item size */
1451           n = strcspn(p, " \t\n");
1452         }
1453       if(*p == '\0')
1454         continue;       /* Line ended */
1455
1456       /* Terminate dev name */
1457       p[n] = '\0';
1458
1459       /* Compare to interface name */
1460       if(!strcmp(p, ifname))
1461         {
1462           /* Save */
1463           target->pcmcia_slot = pcmcia_slot;
1464
1465           /* Activate */
1466           target->active[SELECT_PCMCIASLOT] = 1;
1467
1468           if(verbose)
1469             fprintf(stderr,
1470                     "Querying %s : Got Pcmcia Slot `%d'.\n",
1471                     ifname, target->pcmcia_slot);
1472           /* Exit loop, found it */
1473           break;
1474         }
1475
1476       /* Finished -> next line */
1477     }
1478
1479   /* Cleanup */
1480   free(linebuf);
1481   fclose(stream);
1482
1483   return(target->active[SELECT_PCMCIASLOT] ? 0 : -1);
1484 }
1485
1486 /*------------------------------------------------------------------*/
1487 /*
1488  * Add a sysfs selector to a mapping
1489  */
1490 static int
1491 mapping_addsysfs(struct if_mapping *    ifnode,
1492                  int *                  active,
1493                  char *                 string,
1494                  size_t                 len,
1495                  struct add_extra *     extra,
1496                  int                    linenum)
1497 {
1498   int           findex; /* filename index */
1499   char *        sdup;
1500
1501   /* Check if we have a modifier */
1502   if((extra == NULL) || (extra->modif_pos == NULL))
1503     { 
1504       fprintf(stderr, "Error: No SYSFS filename at line %d\n", linenum);  
1505       return(-1);
1506     }
1507
1508   /* Search if the filename already exist */
1509   for(findex = 0; findex < sysfs_global.filenum; findex++)
1510     {
1511       if(!strcmp(extra->modif_pos, sysfs_global.filename[findex]))
1512         break;
1513     }
1514
1515   /* If filename does not exist, creates it */
1516   if(findex == sysfs_global.filenum)
1517     {
1518       if(findex == SYSFS_MAX_FILE)
1519         {
1520           fprintf(stderr, "Error: Too many SYSFS filenames at line %d\n", linenum);  
1521           return(-1);
1522         }
1523       sdup = strndup(extra->modif_pos, extra->modif_len);
1524       if(sdup == NULL)
1525         {
1526           fprintf(stderr, "Error: Can't allocate SYSFS file\n");  
1527           return(-1);
1528         }
1529       sysfs_global.filename[findex] = sdup;
1530       sysfs_global.filenum++;
1531     }
1532
1533   /* Store value */
1534   sdup = strndup(string, len);
1535   if(sdup == NULL)
1536     {
1537       fprintf(stderr, "Error: Can't allocate SYSFS value\n");  
1538       return(-1);
1539     }
1540   ifnode->sysfs[findex] = sdup;
1541
1542   /* Activate */
1543   ifnode->active[SELECT_SYSFS] = 1;
1544   active[SELECT_SYSFS] = 1;
1545
1546   if(verbose)
1547     fprintf(stderr,
1548             "Parsing : Added SYSFS filename `%s' value `%s' from line %d.\n",
1549             sysfs_global.filename[findex], ifnode->sysfs[findex], linenum);
1550
1551   return(0);
1552 }
1553
1554 /*------------------------------------------------------------------*/
1555 /*
1556  * Compare all the sysfs values of two mappings
1557  */
1558 static int
1559 mapping_cmpsysfs(struct if_mapping *    ifnode,
1560                  struct if_mapping *    target)
1561 {
1562   int           findex; /* filename index */
1563   int           match = 1;
1564
1565   /* Loop on all sysfs selector */
1566   for(findex = 0; findex < sysfs_global.filenum; findex++)
1567     {
1568       /* If the mapping defines this sysfs selector.. */
1569       if(ifnode->sysfs[findex] != NULL)
1570         /* And if the sysfs values don't match */
1571         if((target->sysfs[findex] == NULL) ||
1572            (fnmatch(ifnode->sysfs[findex], target->sysfs[findex],
1573                     FNM_CASEFOLD)))
1574           /* Then the sysfs selector doesn't match */
1575           match = 0;
1576     }
1577
1578   return(!match);
1579 }
1580
1581 /*------------------------------------------------------------------*/
1582 /*
1583  * Extract all the sysfs values of an interface
1584  */
1585 static int
1586 mapping_getsysfs(int                    skfd,
1587                  const char *           ifname,
1588                  struct if_mapping *    target,
1589                  int                    flag)
1590 {
1591   FILE *        stream;
1592   char *        fname;
1593   int           fnsize;
1594   char *        linebuf = NULL;
1595   size_t        linelen = 0; 
1596   char *        sdup;
1597   int           findex; /* filename index */
1598
1599   /* Avoid "Unused parameter" warning */
1600   skfd = skfd;
1601   flag = flag;
1602
1603   /* Check if we know the devpath of this device */
1604   if(target->sysfs_devpath == NULL)
1605     {
1606       /* Check if we know the root of the sysfs filesystem */
1607       if(sysfs_global.root == NULL)
1608         {
1609           /* Open the mount file for reading */
1610           stream = fopen("/proc/mounts", "r");
1611           if(!stream) 
1612             {
1613               fprintf(stderr, "Error: Can't open /proc/mounts file: %s\n",
1614                       strerror(errno)); 
1615               return(-1);
1616             }
1617
1618           /* Read each line of file
1619            * getline is a GNU extension :-( The buffer is recycled and
1620            * increased as needed by getline. */
1621           while(getline(&linebuf, &linelen, stream) > 0)
1622             {
1623               int               i;
1624               char *    p;
1625               size_t    n;
1626               char *    token[3];
1627               size_t    toklen[3];
1628
1629               /* The format of /proc/mounts is similar to /etc/fstab (5).
1630                * The first argument is the device. For sysfs, there is no
1631                * associated device, so this argument is ignored.
1632                * The second argument is the mount point.
1633                * The third argument is the filesystem type.
1634                */
1635
1636               /* Extract the first 3 tokens */
1637               p = linebuf;
1638               for(i = 0; i < 3; i++)
1639                 {
1640                   while(isspace(*p))
1641                     ++p; 
1642                   token[i] = p;
1643                   n = strcspn(p, " \t\n");
1644                   toklen[i] = n;
1645                   p += n;
1646                 }
1647               /* Get the filesystem which type is "sysfs" */
1648               if((n == 5) && (!strncasecmp(token[2], "sysfs", 5)))
1649                 {
1650                   /* Get its mount point */
1651                   n = toklen[1];
1652                   sdup = strndup(token[1], n);
1653                   if((n == 0) || (sdup == NULL))
1654                     {
1655                       fprintf(stderr,
1656                               "Error: Can't parse /proc/mounts file: %s\n",
1657                               strerror(errno)); 
1658                       return(-1);
1659                     }
1660                   /* Store it */
1661                   sysfs_global.root = sdup;
1662                   sysfs_global.rlen = n;
1663                   break;
1664                 }
1665               /* Finished -> next line */
1666             }
1667
1668           /* Cleanup */
1669           fclose(stream);
1670
1671           /* Check if we found it */
1672           if(sysfs_global.root == NULL)
1673             {
1674               fprintf(stderr,
1675                       "Error: Can't find sysfs in /proc/mounts file\n");
1676               free(linebuf);
1677               return(-1);
1678             }
1679         }
1680
1681       /* Construct devpath for this interface.
1682        * Reserve enough space to replace name without realloc. */
1683       fnsize = (sysfs_global.rlen + 11 + IFNAMSIZ + 1);
1684       fname = malloc(fnsize);
1685       if(fname == NULL)
1686         {
1687           fprintf(stderr, "Error: Can't allocate SYSFS devpath\n");  
1688           return(-1);
1689         }
1690       /* Not true devpath for 2.6.20+, but this syslink should work */
1691       target->sysfs_devplen = sprintf(fname, "%s/class/net/%s",
1692                                       sysfs_global.root, ifname);
1693       target->sysfs_devpath = fname;
1694     }
1695
1696   /* Loop on all sysfs selector */
1697   for(findex = 0; findex < sysfs_global.filenum; findex++)
1698     {
1699       char *    p;
1700       ssize_t   n;
1701
1702       /* Construct complete filename for the sysfs selector */
1703       fnsize = (target->sysfs_devplen + 1 +
1704                 strlen(sysfs_global.filename[findex]) + 1);
1705       fname = malloc(fnsize);
1706       if(fname == NULL)
1707         {
1708           fprintf(stderr, "Error: Can't allocate SYSFS filename\n");  
1709           free(linebuf);
1710           return(-1);
1711         }
1712       sprintf(fname, "%s/%s", target->sysfs_devpath,
1713               sysfs_global.filename[findex]);
1714
1715       /* Open the sysfs file for reading */
1716       stream = fopen(fname, "r");
1717       if(!stream) 
1718         {
1719           /* Some sysfs attribute may no exist for some interface */
1720           if(verbose)
1721             fprintf(stderr, "Error: Can't open file `%s': %s\n", fname,
1722                     strerror(errno)); 
1723           /* Next sysfs selector */
1724           continue;
1725         }
1726
1727       /* Read file. Only one line in file. */
1728       n = getline(&linebuf, &linelen, stream);
1729       fclose(stream);
1730       if(n <= 0)
1731         {
1732           /* Some attributes are just symlinks to another directory.
1733            * We can read the attributes in that other directory
1734            * just fine, but sometimes the symlink itself gives a lot
1735            * of information.
1736            * Examples : SYSFS{device} and SYSFS{device/driver}
1737            * In such cases, get the name of the directory pointed to...
1738            */
1739           /*
1740            * I must note that the API for readlink() is very bad,
1741            * which force us to have this ugly code. Yuck !
1742            */
1743           int           allocsize = 128;        /* 256 = Good start */
1744           int           retry = 16;
1745           char *        linkpath = NULL;
1746           int           pathlen;
1747
1748           /* Try reading the link with increased buffer size */
1749           do
1750             {
1751               allocsize *= 2;
1752               linkpath = realloc(linkpath, allocsize);
1753               pathlen = readlink(fname, linkpath, allocsize);
1754               /* If we did not hit the buffer limit, success */
1755               if(pathlen < allocsize)
1756                 break;
1757             }
1758           while(retry-- > 0);
1759
1760           /* Check for error, most likely ENOENT */
1761           if(pathlen > 0)
1762             /* We have a symlink ;-) Terminate the string. */
1763             linkpath[pathlen] = '\0';
1764           else
1765             {
1766               /* Error ! */
1767               free(linkpath);
1768
1769               /* A lot of information in the sysfs is implicit, given
1770                * by the position of a file in the tree. It is therefore
1771                * important to be able to read the various components
1772                * of a path. For this reason, we resolve '..' to the
1773                * real name of the parent directory... */
1774               /* We have at least 11 char, see above */
1775               if(!strcmp(fname + fnsize - 4, "/.."))
1776                 //if(!strcmp(fname + strlen(fname) - 3, "/.."))
1777                 {
1778                   /* This procedure to get the realpath is not very
1779                    * nice, but it's the "best practice". Hmm... */
1780                   int   cwd_fd = open(".", O_RDONLY);
1781                   linkpath = NULL;
1782                   if(cwd_fd > 0)
1783                     {
1784                       int       ret = chdir(fname);
1785                       if(ret == 0)
1786                         /* Using getcwd with NULL is a GNU extension. Nice. */
1787                         linkpath = getcwd(NULL, 0);
1788                       /* This may fail, but it's not fatal */
1789                       fchdir(cwd_fd);
1790                     }
1791                   /* Check if we suceeded */
1792                   if(!linkpath)
1793                     {
1794                       free(linkpath);
1795                       if(verbose)
1796                         fprintf(stderr, "Error: Can't read parent directory `%s'\n", fname);
1797                       /* Next sysfs selector */
1798                       continue;
1799                     }
1800                 }
1801               else
1802                 {
1803                   /* Some sysfs attribute are void for some interface,
1804                    * we may have a real directory, or we may have permission
1805                    * issues... */
1806                   if(verbose)
1807                     fprintf(stderr, "Error: Can't read file `%s'\n", fname);
1808                   /* Next sysfs selector */
1809                   continue;
1810                 }
1811             }
1812
1813           /* Here, we have a link name or a parent directory name */
1814
1815           /* Keep only the last component of path name, save it */
1816           p = basename(linkpath);
1817           sdup = strdup(p);
1818           free(linkpath);
1819         }
1820       else
1821         {
1822           /* This is a regular file (well, pseudo file) */
1823           /* Get content, remove trailing '/n', save it */
1824           p = linebuf;
1825           if(p[n - 1] == '\n')
1826             n--;
1827           sdup = strndup(p, n);
1828         }
1829       if(sdup == NULL)
1830         {
1831           fprintf(stderr, "Error: Can't allocate SYSFS value\n"); 
1832           free(linebuf);
1833           return(-1);
1834         }
1835       target->sysfs[findex] = sdup;
1836
1837       /* Activate */
1838       target->active[SELECT_SYSFS] = 1;
1839
1840       if(verbose)
1841         fprintf(stderr,
1842                 "Querying %s : Got SYSFS filename `%s' value `%s'.\n",
1843                 ifname, sysfs_global.filename[findex], target->sysfs[findex]);
1844
1845       /* Finished : Next sysfs selector */
1846     }
1847
1848   /* Cleanup */
1849   free(linebuf);
1850
1851   return(target->active[SELECT_SYSFS] ? 0 : -1);
1852 }
1853
1854 /*------------------------------------------------------------------*/
1855 /*
1856  * Add a Previous Interface Name selector to a mapping
1857  */
1858 static int
1859 mapping_addprevname(struct if_mapping * ifnode,
1860                    int *                active,
1861                    char *               string,
1862                    size_t               len,
1863                    struct add_extra *   extra,
1864                    int                  linenum)
1865 {
1866   /* Avoid "Unused parameter" warning */
1867   extra = extra;
1868
1869   /* Verify validity of string */
1870   if(len >= sizeof(ifnode->prevname))
1871     { 
1872       fprintf(stderr, "Old Interface Name too long at line %d\n", linenum);  
1873       return(-1);
1874     }
1875
1876   /* Copy */
1877   memcpy(ifnode->prevname, string, len + 1); 
1878
1879   /* Activate */
1880   ifnode->active[SELECT_PREVNAME] = 1;
1881   active[SELECT_PREVNAME] = 1;
1882
1883   if(verbose)
1884     fprintf(stderr,
1885             "Parsing : Added Old Interface Name `%s' from line %d.\n",
1886             ifnode->prevname, linenum);
1887
1888   return(0);
1889 }
1890
1891 /*------------------------------------------------------------------*/
1892 /*
1893  * Compare the Previous Interface Name of two mappings
1894  * Note : this one is special.
1895  */
1896 static int
1897 mapping_cmpprevname(struct if_mapping * ifnode,
1898                    struct if_mapping *  target)
1899 {
1900   /* Do wildcard matching, case insensitive */
1901   return(fnmatch(ifnode->prevname, target->ifname, FNM_CASEFOLD));
1902 }
1903
1904 /*------------------------------------------------------------------*/
1905 /*
1906  * Extract the Previous Interface Name from a live interface
1907  */
1908 static int
1909 mapping_getprevname(int                 skfd,
1910                    const char *         ifname,
1911                    struct if_mapping *  target,
1912                    int                  flag)
1913 {
1914   /* Avoid "Unused parameter" warning */
1915   skfd = skfd; ifname = ifname; flag = flag;
1916
1917   /* Don't do anything, it's already in target->ifname ;-) */
1918
1919   /* Activate */
1920   target->active[SELECT_PREVNAME] = 1;
1921
1922   return(0);
1923 }
1924
1925
1926 /*********************** MAPPING MANAGEMENTS ***********************/
1927 /*
1928  * Manage interface mappings.
1929  * Each mapping tell us how to identify a specific interface name.
1930  * It is composed of a bunch of selector values.
1931  */
1932
1933 /*------------------------------------------------------------------*/
1934 /*
1935  * Create a new interface mapping and verify its name
1936  */
1937 static struct if_mapping *
1938 mapping_create(char *   pos,
1939                int      len,
1940                int      linenum)
1941 {
1942   struct if_mapping *   ifnode;
1943   char *                star;
1944
1945   star = memchr(pos, '*', len);
1946
1947   /* Check overflow, need one extra char for wildcard */
1948   if((len + (star != NULL)) > IFNAMSIZ)
1949     {
1950       fprintf(stderr, "Error: Interface name `%.*s' too long at line %d\n",
1951               (int) len, pos, linenum);  
1952       return(NULL);
1953     }
1954
1955   /* Create mapping, zero it */
1956   ifnode = calloc(1, sizeof(if_mapping));
1957   if(!ifnode)
1958     {
1959       fprintf(stderr, "Error: Can't allocate interface mapping.\n");  
1960       return(NULL);
1961     }
1962
1963   /* Set the name, terminates it */
1964   memcpy(ifnode->ifname, pos, len); 
1965   ifnode->ifname[len] = '\0'; 
1966
1967   /* Check the interface name and issue various pedantic warnings.
1968    * We assume people using takeover want to force interfaces to those
1969    * names and know what they are doing, so don't bother them... */
1970   if((!force_takeover) &&
1971      ((!strcmp(ifnode->ifname, "eth0")) || (!strcmp(ifnode->ifname, "wlan0"))))
1972     fprintf(stderr,
1973             "Warning: Interface name is `%s' at line %d, can't be mapped reliably.\n",
1974             ifnode->ifname, linenum);
1975   if(strchr(ifnode->ifname, ':'))
1976     fprintf(stderr, "Warning: Alias device `%s' at line %d probably can't be mapped.\n",
1977             ifnode->ifname, linenum);
1978
1979   if(verbose)
1980     fprintf(stderr, "Parsing : Added Mapping `%s' from line %d.\n",
1981             ifnode->ifname, linenum);
1982
1983   /* Done */
1984   return(ifnode);
1985 }
1986
1987 /*------------------------------------------------------------------*/
1988 /*
1989  * Find the most appropriate selector matching a given selector name
1990  */
1991 static inline const struct mapping_selector *
1992 selector_find(const char *      string,
1993               size_t            slen,
1994               int               linenum)
1995 {
1996   const struct mapping_selector *       found = NULL;
1997   int                   ambig = 0;
1998   int                   i;
1999
2000   /* Go through all selectors */
2001   for(i = 0; selector_list[i].name != NULL; ++i)
2002     {
2003       /* No match -> next one */
2004       if(strncasecmp(selector_list[i].name, string, slen) != 0)
2005         continue;
2006
2007       /* Exact match -> perfect */
2008       if(slen == strlen(selector_list[i].name))
2009         return &selector_list[i];
2010
2011       /* Partial match */
2012       if(found == NULL)
2013         /* First time */
2014         found = &selector_list[i];
2015       else
2016         /* Another time */
2017         if (selector_list[i].add_fn != found->add_fn)
2018           ambig = 1;
2019     }
2020
2021   if(found == NULL)
2022     {
2023       fprintf(stderr, "Error: Unknown selector `%.*s' at line %d.\n",
2024               (int) slen, string, linenum);
2025       return NULL;
2026     }
2027
2028   if(ambig)
2029     {
2030       fprintf(stderr, "Selector `%.*s'at line %d is ambiguous.\n",
2031               (int) slen, string, linenum);
2032       return NULL;
2033     }
2034
2035   return found;
2036 }
2037
2038 /*------------------------------------------------------------------*/
2039 /*
2040  * Read the configuration file and extract all valid mappings and their
2041  * selectors.
2042  */
2043 static int
2044 mapping_readfile(const char *   filename)
2045 {
2046   FILE *                stream;
2047   char *                linebuf = NULL;
2048   size_t                linelen = 0; 
2049   int                   linenum = 0; 
2050   struct add_extra      extrainfo;
2051
2052   /* Reset the list of filters */
2053   bzero(selector_active, sizeof(selector_active));
2054
2055   /* Check filename */
2056   if(!strcmp(filename, "-"))
2057     {
2058       /* Read from stdin */
2059       stream = stdin;
2060
2061     }
2062   else
2063     {
2064       /* Open the file for reading */
2065       stream = fopen(filename, "r");
2066       if(!stream) 
2067         {
2068           fprintf(stderr, "Error: Can't open configuration file `%s': %s\n",
2069                   filename, strerror(errno)); 
2070           return(-1);
2071         }
2072     }
2073
2074   /* Read each line of file
2075    * getline is a GNU extension :-( The buffer is recycled and increased
2076    * as needed by getline. */
2077   while(getline(&linebuf, &linelen, stream) > 0)
2078     {
2079       struct if_mapping *       ifnode;
2080       char *                    p;
2081       char *                    e;
2082       size_t                    n;
2083       int                       ret = -13;      /* Complain if no selectors */
2084
2085       /* Keep track of line number */
2086       linenum++;
2087
2088       /* Every comments terminates parsing */
2089       if((p = strchr(linebuf,'#')) != NULL)
2090         *p = '\0';
2091
2092       /* Get interface name */
2093       p = linebuf;
2094       while(isspace(*p))
2095         ++p; 
2096       if(*p == '\0')
2097         continue;       /* Line ended */
2098       n = strcspn(p, " \t\n");
2099
2100       /* Create mapping */
2101       ifnode = mapping_create(p, n, linenum);
2102       if(!ifnode)
2103         continue;       /* Ignore this line */
2104       p += n;
2105       p += strspn(p, " \t\n"); 
2106
2107       /* Loop on all selectors */
2108       while(*p != '\0')
2109         {
2110           const struct mapping_selector *       selector = NULL;
2111           struct add_extra *                    extra = NULL;
2112
2113           /* Selector name length - stop at modifier start */
2114           n = strcspn(p, " \t\n{");
2115
2116           /* Find it */
2117           selector = selector_find(p, n, linenum);
2118           if(!selector)
2119             {
2120               ret = -1;
2121               break;
2122             }
2123           p += n;
2124
2125           /* Check for modifier */
2126           if(*p == '{')
2127             {
2128               p++;
2129               /* Find end of modifier */
2130               e = strchr(p, '}');
2131               if(e == NULL)
2132                 {
2133                   fprintf(stderr,
2134                           "Error: unterminated selector modifier value on line %d\n",
2135                           linenum);
2136                   ret = -1;
2137                   break;        /* Line ended */
2138                 }
2139               /* Fill in struct and hook it */
2140               extrainfo.modif_pos = p;
2141               extrainfo.modif_len = e - p;
2142               extra = &extrainfo;
2143               /* Terminate modifier value */
2144               e[0] = '\0';
2145               /* Skip it */
2146               p = e + 1;
2147             }
2148
2149           /* Get to selector value */
2150           p += strspn(p, " \t\n"); 
2151           if(*p == '\0')
2152             {
2153               fprintf(stderr, "Error: no value for selector `%s' on line %d\n",
2154                       selector->name, linenum);
2155               ret = -1;
2156               break;    /* Line ended */
2157             }
2158           /* Check for quoted arguments */
2159           if(*p == '"')
2160             {
2161               p++;
2162               e = strchr(p, '"');
2163               if(e == NULL)
2164                 {
2165                   fprintf(stderr,
2166                           "Error: unterminated quoted value on line %d\n",
2167                           linenum);
2168                   ret = -1;
2169                   break;        /* Line ended */
2170                 }
2171               n = e - p;
2172               e++;
2173             }
2174           else
2175             {
2176               /* Just end at next blank */
2177               n = strcspn(p, " \t\n");
2178               e = p + n;
2179             }
2180           /* Make 'e' point past the '\0' we are going to add */
2181           if(*e != '\0')
2182             e++;
2183           /* Terminate selector value */
2184           p[n] = '\0';
2185
2186           /* Add it to the mapping */
2187           ret = selector->add_fn(ifnode, selector_active, p, n,
2188                                  extra, linenum);
2189           if(ret < 0)
2190             break;
2191
2192           /* Go to next selector */
2193           p = e;
2194           p += strspn(p, " \t\n"); 
2195         }
2196
2197       /* We add a mapping only if it has at least one selector and if all
2198        * selectors were parsed properly. */
2199       if(ret < 0)
2200         {
2201           /* If we have not yet printed an error, now is a good time ;-) */
2202           if(ret == -13)
2203             fprintf(stderr, "Error: Line %d ignored, no valid selectors\n",
2204                     linenum);
2205           else
2206             fprintf(stderr, "Error: Line %d ignored due to prior errors\n",
2207                     linenum);
2208
2209           free(ifnode);
2210         }
2211       else
2212         {
2213           /* Link it in the list */
2214           ifnode->next = mapping_list;
2215           mapping_list = ifnode;
2216         }
2217     }
2218
2219   /* Cleanup */
2220   free(linebuf);
2221
2222   /* Finished reading, close the file */
2223   if(stream != stdin)
2224     fclose(stream);
2225   return(0);
2226 }
2227
2228 /*------------------------------------------------------------------*/
2229 /*
2230  * Extract all the interesting selectors for the interface in consideration
2231  */
2232 static struct if_mapping *
2233 mapping_extract(int             skfd,
2234                 const char *    ifname)
2235 {
2236   struct if_mapping *   target;
2237   int                   i;
2238
2239   /* Create mapping, zero it */
2240   target = calloc(1, sizeof(if_mapping));
2241   if(!target)
2242     {
2243       fprintf(stderr, "Error: Can't allocate interface mapping.\n");  
2244       return(NULL);
2245     }
2246
2247   /* Set the interface name */
2248   strcpy(target->ifname, ifname);
2249
2250   /* Loop on all active selectors */
2251   for(i = 0; i < SELECT_NUM; i++)
2252     {
2253       /* Check if this selector is active */
2254       if(selector_active[i] != 0)
2255         {
2256           /* Extract selector */
2257           selector_list[i].get_fn(skfd, ifname, target, selector_active[i]);
2258
2259           /* Ignore errors. Some mapping may not need all selectors */
2260         }
2261     }
2262
2263   return(target);
2264
2265
2266 /*------------------------------------------------------------------*/
2267 /*
2268  * Find the first mapping in the list matching the one we want.
2269  */
2270 static struct if_mapping *
2271 mapping_find(struct if_mapping *        target)
2272 {
2273   struct if_mapping *   ifnode;
2274   int                   i;
2275
2276   /* Look over all our mappings */
2277   for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next)
2278     {
2279       int               matches = 1;
2280
2281       /* Look over all our selectors, all must match */
2282       for(i = 0; i < SELECT_NUM; i++)
2283         {
2284           /* Check if this selector is active */
2285           if(ifnode->active[i] != 0)
2286             {
2287               /* If this selector doesn't match, game over for this mapping */
2288               if((target->active[i] == 0) ||
2289                  (selector_list[i].cmp_fn(ifnode, target) != 0))
2290                 {
2291                   matches = 0;
2292                   break;
2293                 }
2294             }
2295         }
2296
2297       /* Check is this mapping was "the one" */
2298       if(matches)
2299         return(ifnode);
2300     }
2301
2302   /* Not found */
2303   return(NULL);
2304
2305
2306 /************************** MODULE SUPPORT **************************/
2307 /*
2308  * Load all necessary module so that interfaces do exist.
2309  * This is necessary for system that are fully modular when
2310  * doing the boot time processing, because we need to run before
2311  * 'ifup -a'.
2312  */
2313
2314 /*------------------------------------------------------------------*/
2315 /*
2316  * Probe interfaces based on our list of mappings.
2317  * This is the default, but usually not the best way to do it.
2318  */
2319 static inline void
2320 probe_mappings(int              skfd)
2321 {
2322   struct if_mapping *   ifnode;
2323   struct ifreq          ifr;
2324
2325   /* Look over all our mappings */
2326   for(ifnode = mapping_list; ifnode != NULL; ifnode = ifnode->next)
2327     {
2328       /* Can't load wildcards interface name :-( */
2329       if(strchr(ifnode->ifname, '*') != NULL)
2330         continue;
2331
2332       if(verbose)
2333         fprintf(stderr, "Probing : Trying to load/probe interface [%s]\n",
2334                 ifnode->ifname);
2335
2336       /* Trick the kernel into loading the interface.
2337        * This allow us to not depend on the exact path and
2338        * name of the '/sbin/modprobe' command.
2339        * Obviously, we expect this command to 'fail', as
2340        * the interface will load with the old/wrong name.
2341        */
2342       strncpy(ifr.ifr_name, ifnode->ifname, IFNAMSIZ);
2343       ioctl(skfd, SIOCGIFHWADDR, &ifr);
2344     }
2345 }
2346
2347 /*------------------------------------------------------------------*/
2348 /*
2349  * Probe interfaces based on Debian's config files.
2350  * This allow to enly load modules for interfaces the user want active,
2351  * all built-in interfaces that should remain unconfigured won't
2352  * be probed (and can have mappings).
2353  */
2354 static inline void
2355 probe_debian(int                skfd)
2356 {
2357   FILE *                stream;
2358   char *                linebuf = NULL;
2359   size_t                linelen = 0; 
2360   struct ifreq          ifr;
2361
2362   /* Open Debian config file */
2363   stream = fopen(DEBIAN_CONFIG_FILE, "r");
2364   if(stream == NULL)
2365     {
2366       fprintf(stderr, "Error: can't open file [%s]\n", DEBIAN_CONFIG_FILE);
2367       return;
2368     }
2369
2370   /* Read each line of file
2371    * getline is a GNU extension :-( The buffer is recycled and increased
2372    * as needed by getline. */
2373   while(getline(&linebuf, &linelen, stream) > 0)
2374     {
2375       char *                    p;
2376       char *                    e;
2377       size_t                    n;
2378
2379       /* Check for auto keyword, ignore when commented out */
2380       if(!strncasecmp(linebuf, "auto ", 5))
2381         {
2382           /* Skip "auto" keyword */
2383           p = linebuf + 5;
2384
2385           /* Terminate at first comment */
2386           e = strchr(p, '#');
2387           if(e != NULL)
2388             *e = '\0';
2389
2390           /* Loop on all interfaces given */
2391           while(*p != '\0')
2392             {
2393               /* Interface name length */
2394               n = strcspn(p, " \t\n");
2395
2396               /* Look for end of interface name */
2397               e = p + n;
2398               /* Make 'e' point past the '\0' we are going to add */
2399               if(*e != '\0')
2400                 e++;
2401               /* Terminate interface name */
2402               p[n] = '\0';
2403
2404               if(verbose)
2405                 fprintf(stderr, "Probing : Trying to load interface [%s]\n",
2406                         p);
2407
2408               /* Load interface */
2409               strncpy(ifr.ifr_name, p, IFNAMSIZ);
2410               ioctl(skfd, SIOCGIFHWADDR, &ifr);
2411
2412               /* Go to next interface name */
2413               p = e;
2414               p += strspn(p, " \t\n"); 
2415             }
2416         }
2417     }
2418
2419   /* Done */
2420   fclose(stream);
2421   return;
2422 }
2423
2424 /**************************** MAIN LOGIC ****************************/
2425
2426 /*------------------------------------------------------------------*/
2427 /*
2428  * Rename an interface to a specified new name.
2429  */
2430 static int
2431 process_rename(int      skfd,
2432                char *   ifname,
2433                char *   newname)
2434 {
2435   char          retname[IFNAMSIZ+1];
2436   int           len;
2437   char *        star;
2438
2439   len = strlen(newname);
2440   star = strchr(newname, '*');
2441
2442   /* Check newname length, need one extra char for wildcard */
2443   if((len + (star != NULL)) > IFNAMSIZ)
2444     {
2445       fprintf(stderr, "Error: Interface name `%s' too long.\n",
2446               newname);  
2447       return(-1);
2448     }
2449
2450   /* Change the name of the interface */
2451   if(if_set_name(skfd, ifname, newname, retname) < 0)
2452     {
2453       fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
2454               ifname, newname, strerror(errno)); 
2455       return(-1);
2456     }
2457
2458   /* Always print out the *new* interface name so that
2459    * the calling script can pick it up and know where its interface
2460    * has gone. */
2461   printf("%s\n", retname);
2462
2463   /* Done */
2464   return(0);
2465 }
2466
2467 /*------------------------------------------------------------------*/
2468 /*
2469  * Process a specified interface.
2470  */
2471 static int
2472 process_ifname(int      skfd,
2473                char *   ifname,
2474                char *   args[],
2475                int      count)
2476 {
2477   struct if_mapping *           target;
2478   const struct if_mapping *     mapping;
2479   char                          retname[IFNAMSIZ+1];
2480
2481   /* Avoid "Unused parameter" warning */
2482   args = args; count = count;
2483
2484   /* Get description of this interface */
2485   target = mapping_extract(skfd, ifname);
2486   if(target == NULL)
2487     return(-1);
2488
2489   /* If udev is calling us, get the real devpath. */
2490   if(udev_output)
2491     {
2492       const char *env;
2493       /* It's passed to us as an environment variable */
2494       env = getenv("DEVPATH");
2495       if(env)
2496         {
2497           int   env_len = strlen(env);
2498           target->sysfs_devplen = env_len;
2499           /* Make enough space for new interface name */
2500           target->sysfs_devpath = malloc(env_len + IFNAMSIZ + 1);
2501           if(target->sysfs_devpath != NULL)
2502             memcpy(target->sysfs_devpath, env, env_len + 1);
2503         }
2504       /* We will get a second chance is the user has some sysfs selectors */
2505     }
2506
2507   /* Find matching mapping */
2508   mapping = mapping_find(target);
2509   if(mapping == NULL)
2510     return(-1);
2511
2512   /* If user specified a new name, keep only interfaces that would
2513    * match the new name... */
2514   if((new_name != NULL) && (if_match_ifname(mapping->ifname, new_name) != 0))
2515     return(-1);
2516
2517   /* Check if user want only dry-run.
2518    * Note that, in the case of wildcard, we don't resolve the wildcard.
2519    * That would be tricky to do... */
2520   if(dry_run)
2521     {
2522       strcpy(retname, mapping->ifname);
2523       fprintf(stderr, "Dry-run : Would rename %s to %s.\n",
2524               target->ifname, mapping->ifname);
2525     }
2526   else
2527     {
2528       /* Change the name of the interface */
2529       if(if_set_name(skfd, target->ifname, mapping->ifname, retname) < 0)
2530         {
2531           fprintf(stderr, "Error: cannot change name of %s to %s: %s\n",
2532                   target->ifname, mapping->ifname, strerror(errno)); 
2533           return(-1);
2534         }
2535     }
2536
2537   /* This one matched */
2538   num_mapping_match++;
2539
2540   /* Check if called with an explicit interface name */
2541   if(print_newname)
2542     {
2543       if(!udev_output)
2544         /* Always print out the *new* interface name so that
2545          * the calling script can pick it up and know where its interface
2546          * has gone. */
2547         printf("%s\n", retname);
2548       else
2549         /* udev likes to call us as an IMPORT action. This means that
2550          * we need to return udev the environment variables changed.
2551          * Obviously, we don't want to return anything is nothing changed. */
2552         if(strcmp(target->ifname, retname))
2553           {
2554             char *      pos;
2555             /* Hack */
2556             if(!target->sysfs_devpath)
2557               mapping_getsysfs(skfd, ifname, target, 0);
2558             /* Update devpath. Size is large enough. */
2559             pos = strrchr(target->sysfs_devpath, '/');
2560             if((pos != NULL) && (!strcmp(target->ifname, pos + 1)))
2561               strcpy(pos + 1, retname);
2562             /* Return new environment variables */
2563             printf("DEVPATH=%s\nINTERFACE=%s\nINTERFACE_OLD=%s\n",
2564                    target->sysfs_devpath, retname, target->ifname);
2565           }
2566     }
2567
2568   /* Done */
2569   return(0);
2570 }
2571
2572 /*------------------------------------------------------------------*/
2573 /*
2574  * Process all network interface present on the system.
2575  */
2576 static int
2577 process_iflist(int      skfd,
2578                char *   args[],
2579                int      count,
2580                int      use_probe,
2581                int      is_debian)
2582 {
2583   num_takeover = 0;
2584   num_mapping_match = 0;
2585
2586   /* Load all the necesary modules */
2587   if(use_probe)
2588     {
2589       if(is_debian)
2590         probe_debian(skfd);
2591       else
2592         probe_mappings(skfd);
2593     }
2594
2595   /* Just do it */
2596   iw_enum_devices(skfd, &process_ifname, args, count);
2597
2598   /* Done */
2599   return(0);
2600 }
2601
2602 /******************************* MAIN *******************************/
2603
2604
2605 /*------------------------------------------------------------------*/
2606 /*
2607  */
2608 static void
2609 usage(void)
2610 {
2611   fprintf(stderr, "usage: ifrename [-c configurationfile] [-i ifname] [-p] [-t] [-d] [-D]\n");
2612   exit(1); 
2613 }
2614
2615 /*------------------------------------------------------------------*/
2616 /*
2617  * The main !
2618  */
2619 int
2620 main(int        argc,
2621      char *     argv[]) 
2622 {
2623   const char *  conf_file = DEFAULT_CONF;
2624   char *        ifname = NULL;
2625   int           use_probe = 0;          /* Probe for modules */
2626   int           is_debian = 0;          /* Debian quirks (probing) */
2627   int           print_num_match = 0;    /* Print/Return num of matches */
2628   int           skfd;
2629   int           ret;
2630
2631   /* Loop over all command line options */
2632   while(1)
2633     {
2634       int c = getopt_long(argc, argv, "c:CdDi:n:ptuvV", long_opt, NULL);
2635       if(c == -1)
2636         break;
2637
2638       switch(c)
2639         { 
2640         default:
2641         case '?':
2642           usage(); 
2643         case 'c':
2644           conf_file = optarg;
2645           break;
2646         case 'C':
2647           print_num_match = 1;
2648           break;
2649         case 'd':
2650           is_debian = 1;
2651           break;
2652         case 'D':
2653           dry_run = 1;
2654           break;
2655         case 'i':
2656           ifname = optarg;
2657           break;
2658         case 'n':
2659           new_name = optarg;
2660           break;
2661         case 'p':
2662           use_probe = 1;
2663           break;
2664         case 't':
2665           force_takeover = 1;
2666           break;
2667         case 'u':
2668           udev_output = 1;
2669           break;
2670         case 'v':
2671           printf("%-8.16s  Wireless-Tools version %d\n", "ifrename", WT_VERSION);
2672           return(0);
2673         case 'V':
2674           verbose = 1;
2675           break;
2676         }
2677     }
2678
2679   /* Create a channel to the NET kernel. */
2680   if((skfd = iw_sockets_open()) < 0)
2681     {
2682       perror("socket");
2683       return(-1);
2684     }
2685
2686   /* Check if interface name was specified with -i. */
2687   if(ifname != NULL)
2688     {
2689       /* Check is target name specified */
2690       if(new_name != NULL)
2691         {
2692           /* User want to simply rename an interface to a specified name */
2693           ret = process_rename(skfd, ifname, new_name);
2694         }
2695       else
2696         {
2697           /* Read the specified/default config file, or stdin. */
2698           if(mapping_readfile(conf_file) < 0)
2699             return(-1);
2700
2701           /* Rename only this interface based on mappings
2702            * Mostly used for HotPlug processing (from /etc/hotplug/net.agent)
2703            * or udev processing (from a udev IMPORT rule).
2704            * Process the network interface specified on the command line,
2705            * and return the new name on stdout.
2706            */
2707           print_newname = 1;
2708           ret = process_ifname(skfd, ifname, NULL, 0);
2709         }
2710     }
2711   else
2712     {
2713       /* Read the specified/default config file, or stdin. */
2714       if(mapping_readfile(conf_file) < 0)
2715         return(-1);
2716
2717       /* Rename all system interfaces
2718        * Mostly used for boot time processing (from init scripts).
2719        */
2720       ret = process_iflist(skfd, NULL, 0, use_probe, is_debian);
2721
2722       /* If we do any takeover, the interface list grabbed with
2723        * iw_enum_devices() may get out of sync with the real interfaces,
2724        * and we may miss the victim interface. So, let's go through the
2725        * list again.
2726        * On the other hand, we may have ping pong between two interfaces,
2727        * each claiming the same name, so let's not do it forever...
2728        * Two time should be enough for most configs...
2729        * Note also that takeover is usually done with eth0, and many time
2730        * we fail to probe eth0 because an unrenamed interface was using it,
2731        * so we redo everything also when probing...
2732        * Jean II */
2733       if(force_takeover && (num_takeover || use_probe))
2734         {
2735           /* Play it again, Sam... */
2736           ret = process_iflist(skfd, NULL, 0, use_probe, is_debian);
2737         }
2738
2739       /* Print number of mapping that matched */
2740       if(print_num_match)
2741         {
2742           fprintf(stderr, "Setting : %d mapping matched.\n", num_mapping_match);
2743           ret = num_mapping_match;
2744         }
2745     }
2746
2747   /* Cleanup */
2748   iw_sockets_close(skfd);
2749   return(ret);
2750