ifrename.c 69 KB

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