PXE Boot integriert.
[people/pmueller/ipfire-2.x.git] / src / install+setup / libsmooth / netstuff.c
1 /* SmoothWall libsmooth.
2 *
3 * This program is distributed under the terms of the GNU General Public
4 * Licence. See the file COPYING for details.
5 *
6 * (c) Lawrence Manning, 2001
7 * Contains network library functions.
8 *
9 * $Id: netstuff.c,v 1.19.2.7 2004/11/05 23:40:17 alanh Exp $
10 *
11 */
12
13 #include "libsmooth.h"
14 #include <signal.h>
15
16 extern FILE *flog;
17 extern char *mylog;
18
19 extern char **ctr;
20
21 newtComponent networkform;
22 newtComponent addressentry;
23 newtComponent netmaskentry;
24 newtComponent statictyperadio;
25 newtComponent dhcptyperadio;
26 newtComponent pppoetyperadio;
27 newtComponent pptptyperadio;
28 newtComponent dhcphostnameentry;
29
30 /* acceptable character filter for IP and netmaks entry boxes */
31 static int ip_input_filter(newtComponent entry, void * data, int ch, int cursor)
32 {
33 if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '\r' || ch >= NEWT_KEY_EXTRA_BASE)
34 return ch;
35 return 0;
36 }
37
38 /* This is a groovie dialog for showing network info. Takes a keyvalue list,
39 * a colour and a dhcp flag. Shows the current settings, and rewrites them
40 * if necessary. DHCP flag sets wether to show the dhcp checkbox. */
41 int changeaddress(struct keyvalue *kv, char *colour, int typeflag,
42 char *defaultdhcphostname)
43 {
44 char *addressresult;
45 char *netmaskresult;
46 char *dhcphostnameresult;
47 struct newtExitStruct es;
48 newtComponent header;
49 newtComponent addresslabel;
50 newtComponent netmasklabel;
51 newtComponent dhcphostnamelabel;
52 newtComponent ok, cancel;
53 char message[1000];
54 char temp[STRING_SIZE];
55 char addressfield[STRING_SIZE];
56 char netmaskfield[STRING_SIZE];
57 char typefield[STRING_SIZE];
58 char dhcphostnamefield[STRING_SIZE];
59 int error;
60 int result = 0;
61 char type[STRING_SIZE];
62 int startstatictype = 0;
63 int startdhcptype = 0;
64 int startpppoetype = 0;
65 int startpptptype = 0;
66
67 /* Build some key strings. */
68 sprintf(addressfield, "%s_ADDRESS", colour);
69 sprintf(netmaskfield, "%s_NETMASK", colour);
70 sprintf(typefield, "%s_TYPE", colour);
71 sprintf(dhcphostnamefield, "%s_DHCP_HOSTNAME", colour);
72
73 sprintf(message, ctr[TR_INTERFACE], colour);
74 newtCenteredWindow(44, (typeflag ? 18 : 12), message);
75
76 networkform = newtForm(NULL, NULL, 0);
77
78 sprintf(message, ctr[TR_ENTER_THE_IP_ADDRESS_INFORMATION], colour);
79 header = newtTextboxReflowed(1, 1, message, 42, 0, 0, 0);
80 newtFormAddComponent(networkform, header);
81
82 /* See if we need a dhcp checkbox. If we do, then we shift the contents
83 * of the window down two rows to make room. */
84 if (typeflag)
85 {
86 strcpy(temp, "STATIC"); findkey(kv, typefield, temp);
87 if (strcmp(temp, "STATIC") == 0) startstatictype = 1;
88 if (strcmp(temp, "DHCP") == 0) startdhcptype = 1;
89 if (strcmp(temp, "PPPOE") == 0) startpppoetype = 1;
90 if (strcmp(temp, "PPTP") == 0) startpptptype = 1;
91 statictyperadio = newtRadiobutton(2, 4, ctr[TR_STATIC], startstatictype, NULL);
92 dhcptyperadio = newtRadiobutton(2, 5, "DHCP", startdhcptype, statictyperadio);
93 pppoetyperadio = newtRadiobutton(2, 6, "PPPOE", startpppoetype, dhcptyperadio);
94 pptptyperadio = newtRadiobutton(2, 7, "PPTP", startpptptype, pppoetyperadio);
95 newtFormAddComponents(networkform, statictyperadio, dhcptyperadio,
96 pppoetyperadio, pptptyperadio, NULL);
97 newtComponentAddCallback(statictyperadio, networkdialogcallbacktype, NULL);
98 newtComponentAddCallback(dhcptyperadio, networkdialogcallbacktype, NULL);
99 newtComponentAddCallback(pppoetyperadio, networkdialogcallbacktype, NULL);
100 newtComponentAddCallback(pptptyperadio, networkdialogcallbacktype, NULL);
101 dhcphostnamelabel = newtTextbox(2, 9, 18, 1, 0);
102 newtTextboxSetText(dhcphostnamelabel, ctr[TR_DHCP_HOSTNAME]);
103 strcpy(temp, defaultdhcphostname);
104 findkey(kv, dhcphostnamefield, temp);
105 dhcphostnameentry = newtEntry(20, 9, temp, 20, &dhcphostnameresult, 0);
106 newtFormAddComponent(networkform, dhcphostnamelabel);
107 newtFormAddComponent(networkform, dhcphostnameentry);
108 if (startdhcptype == 0)
109 newtEntrySetFlags(dhcphostnameentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
110 }
111 /* Address */
112 addresslabel = newtTextbox(2, (typeflag ? 11 : 4) + 0, 18, 1, 0);
113 newtTextboxSetText(addresslabel, ctr[TR_IP_ADDRESS_PROMPT]);
114 strcpy(temp, "");
115 findkey(kv, addressfield, temp);
116 addressentry = newtEntry(20, (typeflag ? 11 : 4) + 0, temp, 20, &addressresult, 0);
117 newtEntrySetFilter(addressentry, ip_input_filter, NULL);
118 if (typeflag == 1 && startstatictype == 0 && startpptptype == 0 )
119 newtEntrySetFlags(addressentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
120 newtFormAddComponent(networkform, addresslabel);
121 newtFormAddComponent(networkform, addressentry);
122
123 /* Netmask */
124 netmasklabel = newtTextbox(2, (typeflag ? 11 : 4) + 1, 18, 1, 0);
125 newtTextboxSetText(netmasklabel, ctr[TR_NETMASK_PROMPT]);
126 strcpy(temp, "255.255.255.0"); findkey(kv, netmaskfield, temp);
127 netmaskentry = newtEntry(20, (typeflag ? 11 : 4) + 1, temp, 20, &netmaskresult, 0);
128 newtEntrySetFilter(netmaskentry, ip_input_filter, NULL);
129 if (typeflag == 1 && startstatictype == 0 && startpptptype == 0 )
130 newtEntrySetFlags(netmaskentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
131
132 newtFormAddComponent(networkform, netmasklabel);
133 newtFormAddComponent(networkform, netmaskentry);
134
135 /* Buttons. */
136 ok = newtButton(8, (typeflag ? 14 : 7), ctr[TR_OK]);
137 cancel = newtButton(26, (typeflag ? 14 : 7), ctr[TR_CANCEL]);
138
139 newtFormAddComponents(networkform, ok, cancel, NULL);
140
141 newtRefresh();
142 newtDrawForm(networkform);
143
144 do
145 {
146 error = 0;
147 newtFormRun(networkform, &es);
148
149 if (es.u.co == ok)
150 {
151 /* OK was pressed; verify the contents of each entry. */
152 strcpy(message, ctr[TR_INVALID_FIELDS]);
153
154 strcpy(type, "STATIC");
155 if (typeflag)
156 gettype(type);
157 if (strcmp(type, "STATIC") == 0 || strcmp(type, "PPTP") == 0 )
158 {
159 if (inet_addr(addressresult) == INADDR_NONE)
160 {
161 strcat(message, ctr[TR_IP_ADDRESS_CR]);
162 error = 1;
163 }
164 if (inet_addr(netmaskresult) == INADDR_NONE)
165 {
166 strcat(message, ctr[TR_NETWORK_MASK_CR]);
167 error = 1;
168 }
169 }
170 if (strcmp(type, "DHCP") == 0)
171 {
172 if (!strlen(dhcphostnameresult))
173 {
174 strcat(message, ctr[TR_DHCP_HOSTNAME_CR]);
175 error = 1;
176 }
177 }
178 if (error)
179 errorbox(message);
180 else
181 {
182 /* No errors! Set new values, depending on dhcp flag etc. */
183 if (typeflag)
184 {
185 replacekeyvalue(kv, dhcphostnamefield, dhcphostnameresult);
186 if (strcmp(type, "STATIC") != 0 && strcmp(type, "PPTP") != 0)
187 {
188 replacekeyvalue(kv, addressfield, "0.0.0.0");
189 replacekeyvalue(kv, netmaskfield, "0.0.0.0");
190 }
191 else
192 {
193 replacekeyvalue(kv, addressfield, addressresult);
194 replacekeyvalue(kv, netmaskfield, netmaskresult);
195 }
196 replacekeyvalue(kv, typefield, type);
197 }
198 else
199 {
200 replacekeyvalue(kv, addressfield, addressresult);
201 replacekeyvalue(kv, netmaskfield, netmaskresult);
202 }
203
204 setnetaddress(kv, colour);
205 result = 1;
206 }
207 }
208 }
209 while (error);
210
211 newtFormDestroy(networkform);
212 newtPopWindow();
213
214 return result;
215 }
216
217 /* for pppoe: return string thats type STATIC, DHCP or PPPOE */
218 int gettype(char *type)
219 {
220 newtComponent selected = newtRadioGetCurrent(statictyperadio);
221
222 if (selected == statictyperadio)
223 strcpy(type, "STATIC");
224 else if (selected == dhcptyperadio)
225 strcpy(type, "DHCP");
226 else if (selected == pppoetyperadio)
227 strcpy(type, "PPPOE");
228 else if (selected == pptptyperadio)
229 strcpy(type, "PPTP");
230 else
231 strcpy(type, "ERROR");
232
233 return 0;
234 }
235
236 /* 0.9.9: calculates broadcast too. */
237 int setnetaddress(struct keyvalue *kv, char *colour)
238 {
239 char addressfield[STRING_SIZE];
240 char netaddressfield[STRING_SIZE];
241 char netmaskfield[STRING_SIZE];
242 char broadcastfield[STRING_SIZE];
243 char address[STRING_SIZE];
244 char netmask[STRING_SIZE];
245 unsigned long int intaddress;
246 unsigned long int intnetaddress;
247 unsigned long int intnetmask;
248 unsigned long int intbroadcast;
249 struct in_addr temp;
250 char *netaddress;
251 char *broadcast;
252
253 /* Build some key strings. */
254 sprintf(addressfield, "%s_ADDRESS", colour);
255 sprintf(netaddressfield, "%s_NETADDRESS", colour);
256 sprintf(netmaskfield, "%s_NETMASK", colour);
257 sprintf(broadcastfield, "%s_BROADCAST", colour);
258
259 strcpy(address, ""); findkey(kv, addressfield, address);
260 strcpy(netmask, ""); findkey(kv, netmaskfield, netmask);
261
262 /* Calculate netaddress. Messy.. */
263 intaddress = inet_addr(address);
264 intnetmask = inet_addr(netmask);
265
266 intnetaddress = intaddress & intnetmask;
267 temp.s_addr = intnetaddress;
268 netaddress = inet_ntoa(temp);
269
270 replacekeyvalue(kv, netaddressfield, netaddress);
271
272 intbroadcast = intnetaddress | ~intnetmask;
273 temp.s_addr = intbroadcast;
274 broadcast = inet_ntoa(temp);
275
276 replacekeyvalue(kv, broadcastfield, broadcast);
277
278 return 1;
279 }
280
281 /* Called when dhcp flag is toggled. Toggle disabled state of other 3
282 * controls. */
283 void networkdialogcallbacktype(newtComponent cm, void *data)
284 {
285 char type[STRING_SIZE];
286
287 gettype(type);
288
289 if (strcmp(type, "STATIC") != 0 && strcmp(type, "PPTP") != 0 )
290 {
291 newtEntrySetFlags(addressentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
292 newtEntrySetFlags(netmaskentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
293 }
294 else
295 {
296 newtEntrySetFlags(addressentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_RESET);
297 newtEntrySetFlags(netmaskentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_RESET);
298 }
299 if (strcmp(type, "DHCP") == 0)
300 newtEntrySetFlags(dhcphostnameentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_RESET);
301 else
302 newtEntrySetFlags(dhcphostnameentry, NEWT_FLAG_DISABLED, NEWT_FLAGS_SET);
303
304 newtRefresh();
305 newtDrawForm(networkform);
306 }
307
308 int interfacecheck(struct keyvalue *kv, char *colour)
309 {
310 char temp[STRING_SIZE];
311 char colourfields[NETCHANGE_TOTAL][STRING_SIZE];
312 int c;
313
314 sprintf(colourfields[ADDRESS], "%s_ADDRESS", colour);
315 sprintf(colourfields[NETADDRESS], "%s_NETADDRESS", colour);
316 sprintf(colourfields[NETMASK], "%s_NETMASK", colour);
317
318 for (c = 0; c < 3; c++)
319 {
320 strcpy(temp, ""); findkey(kv, colourfields[c], temp);
321 if (!(strlen(temp))) return 0;
322 }
323 return 1;
324 }
325
326 /* Network probing! */
327 struct nic nics[] = {
328 { "100VG-AnyLan Network Adapters, HP J2585B, J2585A, etc", "hp100" },
329 { "3Com EtherLink III", "3c509" },
330 { "3Com 3c501", "3c501" },
331 { "3Com ISA EtherLink XL", "3c515" },
332 { "3Com 3c503 and 3c503/16", "3c503" },
333 { "3Com EtherLink MC (3c523)", "3c523" },
334 { "3Com EtherLink MC/32 (3c527)", "3c527" },
335 { "3Com EtherLink Plus (3c505)", "3c505" },
336 { "3Com EtherLink 16", "3c507" },
337 { "3Com \"Corkscrew\" EtherLink PCI III/XL, etc.", "3c59x" },
338 { "3Com Typhoon Family (3C990, 3CR990, and variants)", "typhoon" },
339 { "Adaptec Starfire/DuraLAN", "starfire" },
340 { "Alteon AceNIC/3Com 3C985/Netgear GA620 Gigabit", "acenic" },
341 { "AMD8111 based 10/100 Ethernet Controller", "amd8111e" },
342 { "AMD LANCE/PCnetAllied Telesis AT1500, J2405A, etc", "lance" },
343 { "AMD PCnet32 and AMD PCnetPCI", "pcnet32" },
344 { "Ansel Communications EISA 3200", "ac3200" },
345 { "Apricot 680x0 VME, 82596 chipset", "82596" },
346 { "AT1700/1720", "at1700" },
347 { "Broadcom 4400", "b44" },
348 { "Broadcom Tigon3", "tg3" },
349 { "Cabletron E2100 series ethercards", "e2100" },
350 { "CATC USB NetMate-based Ethernet", "catc" },
351 { "CDC USB Ethernet", "CDCEther" },
352 { "Crystal LAN CS8900/CS8920", "cs89x0" },
353 { "Compaq Netelligent 10/100 TX PCI UTP, etc", "tlan" },
354 { "D-Link DL2000-based Gigabit Ethernet", "dl2k" },
355 { "Digi Intl. RightSwitch SE-X EISA and PCI", "dgrs" },
356 { "Digital 21x4x Tulip PCI ethernet cards, etc.", "tulip" },
357 { "Digital DEPCA & EtherWORKS,DEPCA, DE100, etc", "depca" },
358 { "DM9102 PCI Fast Ethernet Adapter", "dmfe", },
359 { "Dummy Network Card (testing)", "dummy", },
360 { "EtherWORKS DE425 TP/COAX EISA, DE434 TP PCI, etc.", "de4x5" },
361 { "EtherWORKS 3 (DE203, DE204 and DE205)", "ewrk3" },
362 { "HP PCLAN/plus", "hp-plus" },
363 { "HP LAN ethernet", "hp" },
364 { "IBM LANA", "ibmlana" },
365 { "ICL EtherTeam 16i/32" ,"eth16i" },
366 { "Intel i82557/i82558 PCI EtherExpressPro", "e100" },
367 { "Intel EtherExpress Cardbus Ethernet", "eepro100_cb" },
368 { "Intel i82595 ISA EtherExpressPro10/10+ driver" ,"eepro" },
369 { "Intel EtherExpress 16 (i82586)", "eexpress" },
370 { "Intel Panther onboard i82596 driver", "lp486e" },
371 { "Intel PRO/1000 Gigabit Ethernet", "e1000" },
372 { "KLSI USB KL5USB101-based", "kaweth" },
373 { "MiCom-Interlan NI5010 ethercard", "ni5010" },
374 { "Mylex EISA LNE390A/B", "lne390", },
375 { "Myson MTD-8xx PCI Ethernet", "fealnx" },
376 { "National Semiconductor DP8381x" , "natsemi" },
377 { "National Semiconductor DP83820" , "ns83820" },
378 { "NE/2 MCA", "ne2" },
379 { "NE2000 PCI cards, RealTEk RTL-8029, etc", "ne2k-pci" },
380 { "NE1000 / NE2000 (non-pci)", "ne" },
381 { "NI50 card (i82586 Ethernet chip)", "ni52" },
382 { "NI6510, ni6510 EtherBlaster", "ni65" },
383 { "Novell/Eagle/Microdyne NE3210 EISA", "ne3210" },
384 { "NVidia Nforce2 Driver", "forcedeth" },
385 { "Packet Engines Hamachi GNIC-II", "hamachi" },
386 { "Packet Engines Yellowfin Gigabit-NIC", "yellowfin" },
387 { "Pegasus/Pegasus-II USB ethernet", "pegasus" },
388 { "PureData PDUC8028,WD8003 and WD8013 compatibles", "wd" },
389 { "Racal-Interlan EISA ES3210", "es3210" },
390 { "RealTek RTL-8139 Fast Ethernet", "8139too" },
391 { "RealTek RTL-8139C+ series 10/100 PCI Ethernet", "8139cp" },
392 { "RealTek RTL-8150 USB ethernet", "rtl8150" },
393 { "RealTek RTL-8169 Gigabit Ethernet", "r8169" },
394 { "SiS 900 PCI", "sis900" },
395 { "SKnet MCA", "sk_mca" },
396 { "SMC 9000 series of ethernet cards", "smc9194" },
397 { "SMC EtherPower II", "epic100" },
398 { "SMC Ultra/EtherEZ ISA/PnP Ethernet", "smc-ultra" },
399 { "SMC Ultra32 EISA Ethernet", "smc-ultra32" },
400 { "SMC Ultra MCA Ethernet", "smc-mca" },
401 { "Sundance Alta", "sundance" },
402 { "SysKonnect SK-98xx", "sk98lin" },
403 { "Toshiba TC35815 Ethernet", "tc35815" },
404 { "Tulip chipset Cardbus Ethernet", "tulip_cb" },
405 { "USB Ethernet", "usbnet" },
406 { "VIA Rhine PCI Fast Ethernet, etc", "via-rhine" },
407 { "Winbond W89c840 Ethernet", "winbond-840" },
408 { "Xircom Cardbus Ethernet", "xircom_cb" },
409 { "Xircom (tulip-like) Cardbus Ethernet", "xircom_tulip_cb" },
410 { NULL, NULL }
411 };
412
413 /* Funky routine for loading all drivers (cept those are already loaded.). */
414 int probecards(char *driver, char *driveroptions)
415 {
416 char message[1000];
417 char commandstring[STRING_SIZE];
418 FILE *handle;
419 char line[STRING_SIZE];
420
421 sprintf(commandstring, "/bin/probenic.sh 1");
422 sprintf(message, ctr[TR_PROBING_FOR_NICS]);
423 runcommandwithstatus(commandstring, message);
424
425 if ((handle = fopen("/nicdriver", "r")))
426 {
427 char *driver;
428 fgets(line, STRING_SIZE-1, handle);
429 fclose(handle);
430 line[strlen(line) - 1] = 0;
431 driver = strtok(line, ".");
432 fprintf(flog, "Detected NIC driver %s\n",driver);
433 if (strlen(driver) > 1) {
434 strcpy(driveroptions, "");
435 return 1;
436 }
437 }
438 strcpy(driver, "");
439 strcpy(driveroptions, "");
440
441 return 0;
442 }
443
444 /* A listbox for selected the card... with a * MANUAL * entry at top for
445 * manual module names. */
446 int choosecards(char *driver, char *driveroptions)
447 {
448 int c;
449 char **sections;
450 int drivercount;
451 int rc;
452 int choice;
453 char commandstring[STRING_SIZE];
454 char message[STRING_SIZE];
455 int done = 0;
456
457 /* Count 'em */
458 c = 0; drivercount = 0;
459 while (nics[c].modulename)
460 {
461 drivercount++;
462 c++;
463 }
464 drivercount++;
465 sections = malloc((drivercount + 1) * sizeof(char *));
466
467 /* Copy 'em. */
468 c = 0;
469 sections[c] = ctr[TR_MANUAL];
470 c++;
471 while (nics[c - 1].modulename)
472 {
473 sections[c] = nics[c - 1].description;
474 c++;
475 }
476 sections[c] = NULL;
477
478 strcpy(driver, "");
479 strcpy(driveroptions, "");
480
481 done = 0; choice = 1;
482 while (!done)
483 {
484 rc = newtWinMenu(ctr[TR_SELECT_NETWORK_DRIVER],
485 ctr[TR_SELECT_NETWORK_DRIVER_LONG], 50, 5, 5, 6,
486 sections, &choice, ctr[TR_OK], ctr[TR_CANCEL], NULL);
487 if (rc == 0 || rc == 1)
488 {
489 if (choice > 0)
490 {
491 /* Find module number, load module. */
492 c = choice - 1;
493
494 if (!checkformodule(nics[c].modulename))
495 {
496 sprintf(commandstring, "/sbin/modprobe %s", nics[c].modulename);
497 sprintf(message, ctr[TR_LOOKING_FOR_NIC], nics[c].description);
498 if (runcommandwithstatus(commandstring, message) == 0)
499 {
500 strcpy(driver, nics[c].modulename);
501 strcpy(driveroptions, "");
502 done = 1;
503 }
504 else
505 errorbox(ctr[TR_UNABLE_TO_LOAD_DRIVER_MODULE]);
506 }
507 else
508 errorbox(ctr[TR_THIS_DRIVER_MODULE_IS_ALREADY_LOADED]);
509 }
510 else
511 {
512 manualdriver(driver, driveroptions);
513 if (strlen(driver))
514 done = 1;
515 }
516 }
517 else
518 done = 1;
519 }
520
521 return 1;
522 }
523
524 /* Manual entry for gurus. */
525 int manualdriver(char *driver, char *driveroptions)
526 {
527 char *values[] = { NULL, NULL }; /* pointers for the values. */
528 struct newtWinEntry entries[] =
529 { { "", &values[0], 0,}, { NULL, NULL, 0 } };
530 int rc;
531 char commandstring[STRING_SIZE];
532 char *driverend;
533
534 strcpy(driver, "");
535 strcpy(driveroptions, "");
536
537 rc = newtWinEntries(ctr[TR_SELECT_NETWORK_DRIVER],
538 ctr[TR_MODULE_PARAMETERS], 50, 5, 5, 40, entries,
539 ctr[TR_OK], ctr[TR_CANCEL], NULL);
540 if (rc == 0 || rc == 1)
541 {
542 if (strlen(values[0]))
543 {
544 sprintf(commandstring, "/sbin/modprobe %s", values[0]);
545 if (runcommandwithstatus(commandstring, ctr[TR_LOADING_MODULE]) == 0)
546 {
547 if ((driverend = strchr(values[0], ' ')))
548 {
549 *driverend = '\0';
550 strcpy(driver, values[0]);
551 strcpy(driveroptions, driverend + 1);
552 }
553 else
554 {
555 strcpy(driver, values[0]);
556 strcpy(driveroptions, "");
557 }
558 }
559 else
560 errorbox(ctr[TR_UNABLE_TO_LOAD_DRIVER_MODULE]);
561 }
562 else
563 errorbox(ctr[TR_MODULE_NAME_CANNOT_BE_BLANK]);
564 }
565 free(values[0]);
566
567 return 1;
568 }
569
570 /* Returns the total number of nics current available as ethX devices. */
571 int countcards(void)
572 {
573 FILE *file;
574 char buffer[STRING_SIZE];
575 char *start;
576 int niccount = 0;
577
578 if (!(file = fopen("/proc/net/dev", "r")))
579 {
580 fprintf(flog, "Unable to open /proc/net/dev in countnics()\n");
581 return 0;
582 }
583
584 while (fgets(buffer, STRING_SIZE, file))
585 {
586 start = buffer;
587 while (*start == ' ') start++;
588 if (strncmp(start, "eth", strlen("eth")) == 0)
589 niccount++;
590 if (strncmp(start, "dummy", strlen("dummy")) == 0)
591 niccount++;
592 }
593
594 fclose(file);
595
596 return niccount;
597 }
598
599 /* Finds the listed module name and copies the card description back. */
600 int findnicdescription(char *modulename, char *description)
601 {
602 int c = 0;
603
604 if (strcmp(modulename, "pcmcia") == 0) {
605 strcpy(description, "PCMCIA Ethernet card");
606 return 0;
607 }
608
609 while (nics[c].description)
610 {
611 if (strcmp(nics[c].modulename, modulename) == 0)
612 {
613 strcpy(description, nics[c].description);
614 return 1;
615 }
616 c++;
617 }
618
619 strcpy(description, "UNKNOWN");
620 return 0;
621 }