source: MondoRescue/branches/stable/mindi-busybox/networking/arp.c@ 1842

Last change on this file since 1842 was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

  • Property svn:eol-style set to native
File size: 11.2 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * arp.c - Manipulate the system ARP cache
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 * Author: Fred N. van Kempen, <waltje at uwalt.nl.mugnet.org>
11 * Busybox port: Paul van Gool <pvangool at mimotech.com>
12 *
13 * modified for getopt32 by Arne Bernin <arne [at] alamut.de>
14 */
15
16#include "libbb.h"
17#include "inet_common.h"
18
19#include <arpa/inet.h>
20#include <net/if.h>
21#include <net/if_arp.h>
22#include <netinet/ether.h>
23#include <netpacket/packet.h>
24
25#define DEBUG 0
26
27#define DFLT_AF "inet"
28#define DFLT_HW "ether"
29
30#define ARP_OPT_A (0x1)
31#define ARP_OPT_p (0x2)
32#define ARP_OPT_H (0x4)
33#define ARP_OPT_t (0x8)
34#define ARP_OPT_i (0x10)
35#define ARP_OPT_a (0x20)
36#define ARP_OPT_d (0x40)
37#define ARP_OPT_n (0x80) /* do not resolve addresses */
38#define ARP_OPT_D (0x100) /* HW-address is devicename */
39#define ARP_OPT_s (0x200)
40#define ARP_OPT_v (0x400 * DEBUG) /* debugging output flag */
41
42
43static const struct aftype *ap; /* current address family */
44static const struct hwtype *hw; /* current hardware type */
45static int sockfd; /* active socket descriptor */
46static smallint hw_set; /* flag if hw-type was set (-H) */
47static const char *device = ""; /* current device */
48
49static const char options[] ALIGN1 =
50 "pub\0"
51 "priv\0"
52 "temp\0"
53 "trail\0"
54 "dontpub\0"
55 "auto\0"
56 "dev\0"
57 "netmask\0";
58
59/* Delete an entry from the ARP cache. */
60/* Called only from main, once */
61static int arp_del(char **args)
62{
63 char *host;
64 struct arpreq req;
65 struct sockaddr sa;
66 int flags = 0;
67 int err;
68
69 memset(&req, 0, sizeof(req));
70
71 /* Resolve the host name. */
72 host = *args;
73 if (ap->input(host, &sa) < 0) {
74 bb_herror_msg_and_die("%s", host);
75 }
76
77 /* If a host has more than one address, use the correct one! */
78 memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr));
79
80 if (hw_set)
81 req.arp_ha.sa_family = hw->type;
82
83 req.arp_flags = ATF_PERM;
84 args++;
85 while (*args != NULL) {
86 switch (index_in_strings(options, *args)) {
87 case 0: /* "pub" */
88 flags |= 1;
89 args++;
90 break;
91 case 1: /* "priv" */
92 flags |= 2;
93 args++;
94 break;
95 case 2: /* "temp" */
96 req.arp_flags &= ~ATF_PERM;
97 args++;
98 break;
99 case 3: /* "trail" */
100 req.arp_flags |= ATF_USETRAILERS;
101 args++;
102 break;
103 case 4: /* "dontpub" */
104#ifdef HAVE_ATF_DONTPUB
105 req.arp_flags |= ATF_DONTPUB;
106#else
107 bb_error_msg("feature ATF_DONTPUB is not supported");
108#endif
109 args++;
110 break;
111 case 5: /* "auto" */
112#ifdef HAVE_ATF_MAGIC
113 req.arp_flags |= ATF_MAGIC;
114#else
115 bb_error_msg("feature ATF_MAGIC is not supported");
116#endif
117 args++;
118 break;
119 case 6: /* "dev" */
120 if (*++args == NULL)
121 bb_show_usage();
122 device = *args;
123 args++;
124 break;
125 case 7: /* "netmask" */
126 if (*++args == NULL)
127 bb_show_usage();
128 if (strcmp(*args, "255.255.255.255") != 0) {
129 host = *args;
130 if (ap->input(host, &sa) < 0) {
131 bb_herror_msg_and_die("%s", host);
132 }
133 memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr));
134 req.arp_flags |= ATF_NETMASK;
135 }
136 args++;
137 break;
138 default:
139 bb_show_usage();
140 break;
141 }
142 }
143 if (flags == 0)
144 flags = 3;
145
146 strncpy(req.arp_dev, device, sizeof(req.arp_dev));
147
148 err = -1;
149
150 /* Call the kernel. */
151 if (flags & 2) {
152 if (option_mask32 & ARP_OPT_v)
153 bb_error_msg("SIOCDARP(nopub)");
154 err = ioctl(sockfd, SIOCDARP, &req);
155 if (err < 0) {
156 if (errno == ENXIO) {
157 if (flags & 1)
158 goto nopub;
159 printf("No ARP entry for %s\n", host);
160 return -1;
161 }
162 bb_perror_msg_and_die("SIOCDARP(priv)");
163 }
164 }
165 if ((flags & 1) && err) {
166 nopub:
167 req.arp_flags |= ATF_PUBL;
168 if (option_mask32 & ARP_OPT_v)
169 bb_error_msg("SIOCDARP(pub)");
170 if (ioctl(sockfd, SIOCDARP, &req) < 0) {
171 if (errno == ENXIO) {
172 printf("No ARP entry for %s\n", host);
173 return -1;
174 }
175 bb_perror_msg_and_die("SIOCDARP(pub)");
176 }
177 }
178 return 0;
179}
180
181/* Get the hardware address to a specified interface name */
182static void arp_getdevhw(char *ifname, struct sockaddr *sa,
183 const struct hwtype *hwt)
184{
185 struct ifreq ifr;
186 const struct hwtype *xhw;
187
188 strcpy(ifr.ifr_name, ifname);
189 ioctl_or_perror_and_die(sockfd, SIOCGIFHWADDR, &ifr,
190 "cant get HW-Address for '%s'", ifname);
191 if (hwt && (ifr.ifr_hwaddr.sa_family != hw->type)) {
192 bb_error_msg_and_die("protocol type mismatch");
193 }
194 memcpy(sa, &(ifr.ifr_hwaddr), sizeof(struct sockaddr));
195
196 if (option_mask32 & ARP_OPT_v) {
197 xhw = get_hwntype(ifr.ifr_hwaddr.sa_family);
198 if (!xhw || !xhw->print) {
199 xhw = get_hwntype(-1);
200 }
201 bb_error_msg("device '%s' has HW address %s '%s'",
202 ifname, xhw->name,
203 xhw->print((char *) &ifr.ifr_hwaddr.sa_data));
204 }
205}
206
207/* Set an entry in the ARP cache. */
208/* Called only from main, once */
209static int arp_set(char **args)
210{
211 char *host;
212 struct arpreq req;
213 struct sockaddr sa;
214 int flags;
215
216 memset(&req, 0, sizeof(req));
217
218 host = *args++;
219 if (ap->input(host, &sa) < 0) {
220 bb_herror_msg_and_die("%s", host);
221 }
222 /* If a host has more than one address, use the correct one! */
223 memcpy(&req.arp_pa, &sa, sizeof(struct sockaddr));
224
225 /* Fetch the hardware address. */
226 if (*args == NULL) {
227 bb_error_msg_and_die("need hardware address");
228 }
229 if (option_mask32 & ARP_OPT_D) {
230 arp_getdevhw(*args++, &req.arp_ha, hw_set ? hw : NULL);
231 } else {
232 if (hw->input(*args++, &req.arp_ha) < 0) {
233 bb_error_msg_and_die("invalid hardware address");
234 }
235 }
236
237 /* Check out any modifiers. */
238 flags = ATF_PERM | ATF_COM;
239 while (*args != NULL) {
240 switch (index_in_strings(options, *args)) {
241 case 0: /* "pub" */
242 flags |= ATF_PUBL;
243 args++;
244 break;
245 case 1: /* "priv" */
246 flags &= ~ATF_PUBL;
247 args++;
248 break;
249 case 2: /* "temp" */
250 flags &= ~ATF_PERM;
251 args++;
252 break;
253 case 3: /* "trail" */
254 flags |= ATF_USETRAILERS;
255 args++;
256 break;
257 case 4: /* "dontpub" */
258#ifdef HAVE_ATF_DONTPUB
259 flags |= ATF_DONTPUB;
260#else
261 bb_error_msg("feature ATF_DONTPUB is not supported");
262#endif
263 args++;
264 break;
265 case 5: /* "auto" */
266#ifdef HAVE_ATF_MAGIC
267 flags |= ATF_MAGIC;
268#else
269 bb_error_msg("feature ATF_MAGIC is not supported");
270#endif
271 args++;
272 break;
273 case 6: /* "dev" */
274 if (*++args == NULL)
275 bb_show_usage();
276 device = *args;
277 args++;
278 break;
279 case 7: /* "netmask" */
280 if (*++args == NULL)
281 bb_show_usage();
282 if (strcmp(*args, "255.255.255.255") != 0) {
283 host = *args;
284 if (ap->input(host, &sa) < 0) {
285 bb_herror_msg_and_die("%s", host);
286 }
287 memcpy(&req.arp_netmask, &sa, sizeof(struct sockaddr));
288 flags |= ATF_NETMASK;
289 }
290 args++;
291 break;
292 default:
293 bb_show_usage();
294 break;
295 }
296 }
297
298 /* Fill in the remainder of the request. */
299 req.arp_flags = flags;
300
301 strncpy(req.arp_dev, device, sizeof(req.arp_dev));
302
303 /* Call the kernel. */
304 if (option_mask32 & ARP_OPT_v)
305 bb_error_msg("SIOCSARP()");
306 xioctl(sockfd, SIOCSARP, &req);
307 return 0;
308}
309
310
311/* Print the contents of an ARP request block. */
312static void
313arp_disp(const char *name, char *ip, int type, int arp_flags,
314 char *hwa, char *mask, char *dev)
315{
316 const struct hwtype *xhw;
317
318 xhw = get_hwntype(type);
319 if (xhw == NULL)
320 xhw = get_hwtype(DFLT_HW);
321
322 printf("%s (%s) at ", name, ip);
323
324 if (!(arp_flags & ATF_COM)) {
325 if (arp_flags & ATF_PUBL)
326 printf("* ");
327 else
328 printf("<incomplete> ");
329 } else {
330 printf("%s [%s] ", hwa, xhw->name);
331 }
332
333 if (arp_flags & ATF_NETMASK)
334 printf("netmask %s ", mask);
335
336 if (arp_flags & ATF_PERM)
337 printf("PERM ");
338 if (arp_flags & ATF_PUBL)
339 printf("PUP ");
340#ifdef HAVE_ATF_MAGIC
341 if (arp_flags & ATF_MAGIC)
342 printf("AUTO ");
343#endif
344#ifdef HAVE_ATF_DONTPUB
345 if (arp_flags & ATF_DONTPUB)
346 printf("DONTPUB ");
347#endif
348 if (arp_flags & ATF_USETRAILERS)
349 printf("TRAIL ");
350
351 printf("on %s\n", dev);
352}
353
354/* Display the contents of the ARP cache in the kernel. */
355/* Called only from main, once */
356static int arp_show(char *name)
357{
358 const char *host;
359 const char *hostname;
360 FILE *fp;
361 struct sockaddr sa;
362 int type, flags;
363 int num;
364 unsigned entries = 0, shown = 0;
365 char ip[128];
366 char hwa[128];
367 char mask[128];
368 char line[128];
369 char dev[128];
370
371 host = NULL;
372 if (name != NULL) {
373 /* Resolve the host name. */
374 if (ap->input(name, &sa) < 0) {
375 bb_herror_msg_and_die("%s", name);
376 }
377 host = xstrdup(ap->sprint(&sa, 1));
378 }
379 fp = xfopen("/proc/net/arp", "r");
380 /* Bypass header -- read one line */
381 fgets(line, sizeof(line), fp);
382
383 /* Read the ARP cache entries. */
384 while (fgets(line, sizeof(line), fp)) {
385
386 mask[0] = '-'; mask[1] = '\0';
387 dev[0] = '-'; dev[1] = '\0';
388 /* All these strings can't overflow
389 * because fgets above reads limited amount of data */
390 num = sscanf(line, "%s 0x%x 0x%x %s %s %s\n",
391 ip, &type, &flags, hwa, mask, dev);
392 if (num < 4)
393 break;
394
395 entries++;
396 /* if the user specified hw-type differs, skip it */
397 if (hw_set && (type != hw->type))
398 continue;
399
400 /* if the user specified address differs, skip it */
401 if (host && strcmp(ip, host) != 0)
402 continue;
403
404 /* if the user specified device differs, skip it */
405 if (device[0] && strcmp(dev, device) != 0)
406 continue;
407
408 shown++;
409 /* This IS ugly but it works -be */
410 hostname = "?";
411 if (!(option_mask32 & ARP_OPT_n)) {
412 if (ap->input(ip, &sa) < 0)
413 hostname = ip;
414 else
415 hostname = ap->sprint(&sa, (option_mask32 & ARP_OPT_n) | 0x8000);
416 if (strcmp(hostname, ip) == 0)
417 hostname = "?";
418 }
419
420 arp_disp(hostname, ip, type, flags, hwa, mask, dev);
421 }
422 if (option_mask32 & ARP_OPT_v)
423 printf("Entries: %d\tSkipped: %d\tFound: %d\n",
424 entries, entries - shown, shown);
425
426 if (!shown) {
427 if (hw_set || host || device[0])
428 printf("No match found in %d entries\n", entries);
429 }
430 if (ENABLE_FEATURE_CLEAN_UP) {
431 free((char*)host);
432 fclose(fp);
433 }
434 return 0;
435}
436
437int arp_main(int argc, char **argv);
438int arp_main(int argc, char **argv)
439{
440 char *hw_type;
441 char *protocol;
442
443 /* Initialize variables... */
444 ap = get_aftype(DFLT_AF);
445 if (!ap)
446 bb_error_msg_and_die("%s: %s not supported", DFLT_AF, "address family");
447
448 getopt32(argv, "A:p:H:t:i:adnDsv", &protocol, &protocol,
449 &hw_type, &hw_type, &device);
450 argv += optind;
451 if (option_mask32 & ARP_OPT_A || option_mask32 & ARP_OPT_p) {
452 ap = get_aftype(protocol);
453 if (ap == NULL)
454 bb_error_msg_and_die("%s: unknown %s", protocol, "address family");
455 }
456 if (option_mask32 & ARP_OPT_A || option_mask32 & ARP_OPT_p) {
457 hw = get_hwtype(hw_type);
458 if (hw == NULL)
459 bb_error_msg_and_die("%s: unknown %s", hw_type, "hardware type");
460 hw_set = 1;
461 }
462 //if (option_mask32 & ARP_OPT_i)... -i
463
464 if (ap->af != AF_INET) {
465 bb_error_msg_and_die("%s: kernel only supports 'inet'", ap->name);
466 }
467
468 /* If no hw type specified get default */
469 if (!hw) {
470 hw = get_hwtype(DFLT_HW);
471 if (!hw)
472 bb_error_msg_and_die("%s: %s not supported", DFLT_HW, "hardware type");
473 }
474
475 if (hw->alen <= 0) {
476 bb_error_msg_and_die("%s: %s without ARP support",
477 hw->name, "hardware type");
478 }
479 sockfd = xsocket(AF_INET, SOCK_DGRAM, 0);
480
481 /* Now see what we have to do here... */
482 if (option_mask32 & (ARP_OPT_d|ARP_OPT_s)) {
483 if (argv[0] == NULL)
484 bb_error_msg_and_die("need host name");
485 if (option_mask32 & ARP_OPT_s)
486 return arp_set(argv);
487 return arp_del(argv);
488 }
489 //if (option_mask32 & ARP_OPT_a) - default
490 return arp_show(argv[0]);
491}
Note: See TracBrowser for help on using the repository browser.