diff options
author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2002-07-03 11:46:38 +0000 |
---|---|---|
committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2002-07-03 11:46:38 +0000 |
commit | 900987843e32563488974222031be9c97c060610 (patch) | |
tree | 905d4f1b1e557950272ac98e1540fa06f732f42f /libbb | |
parent | 26e899536049e29919abd9101799745ceaffff25 (diff) | |
download | busybox-w32-900987843e32563488974222031be9c97c060610.tar.gz busybox-w32-900987843e32563488974222031be9c97c060610.tar.bz2 busybox-w32-900987843e32563488974222031be9c97c060610.zip |
This patch from Bart Visscher <magick@linux-fan.com> adds
IPV6 support to busybox. This patch does the following:
* Add IPv6 support to libbb
* Enable IPv6 interface address display
* Add IPv6 config option
* Adds ping6, an adaptation of the ping applet for IPv6
* Adds support routines for ping6:
- xgethostbyname2
- create_icmp6_socket
* Adds ifconfig support for IPv6
* Add support IPv6 to netstat
* Add IPv6 support to route
Thanks Bart!
git-svn-id: svn://busybox.net/trunk/busybox@5003 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/Makefile.in | 4 | ||||
-rw-r--r-- | libbb/create_icmp6_socket.c | 39 | ||||
-rw-r--r-- | libbb/inet_common.c | 64 | ||||
-rw-r--r-- | libbb/interface.c | 101 | ||||
-rw-r--r-- | libbb/xgethostbyname2.c | 37 |
5 files changed, 238 insertions, 7 deletions
diff --git a/libbb/Makefile.in b/libbb/Makefile.in index 2af70f8c7..70cc26dc1 100644 --- a/libbb/Makefile.in +++ b/libbb/Makefile.in | |||
@@ -40,7 +40,9 @@ LIBBB_SRC:= \ | |||
40 | dirname.c make_directory.c create_icmp_socket.c u_signal_names.c arith.c \ | 40 | dirname.c make_directory.c create_icmp_socket.c u_signal_names.c arith.c \ |
41 | simplify_path.c inet_common.c inode_hash.c obscure.c pwd2spwd.c xfuncs.c \ | 41 | simplify_path.c inet_common.c inode_hash.c obscure.c pwd2spwd.c xfuncs.c \ |
42 | correct_password.c change_identity.c setup_environment.c run_shell.c \ | 42 | correct_password.c change_identity.c setup_environment.c run_shell.c \ |
43 | pw_encrypt.c restricted_shell.c | 43 | pw_encrypt.c restricted_shell.c xgethostbyname2.c create_icmp6_socket.c \ |
44 | xconnect.c | ||
45 | |||
44 | LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) | 46 | LIBBB_OBJS=$(patsubst %.c,$(LIBBB_DIR)%.o, $(LIBBB_SRC)) |
45 | 47 | ||
46 | LIBBB_MSRC:=$(LIBBB_DIR)messages.c | 48 | LIBBB_MSRC:=$(LIBBB_DIR)messages.c |
diff --git a/libbb/create_icmp6_socket.c b/libbb/create_icmp6_socket.c new file mode 100644 index 000000000..a09565605 --- /dev/null +++ b/libbb/create_icmp6_socket.c | |||
@@ -0,0 +1,39 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * create raw socket for icmp (IPv6 version) protocol test permision | ||
6 | * and drop root privilegies if running setuid | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <netdb.h> | ||
12 | #include <sys/socket.h> | ||
13 | #include <errno.h> | ||
14 | #include <unistd.h> | ||
15 | #include "libbb.h" | ||
16 | |||
17 | #if CONFIG_FEATURE_IPV6 | ||
18 | int create_icmp6_socket(void) | ||
19 | { | ||
20 | struct protoent *proto; | ||
21 | int sock; | ||
22 | |||
23 | proto = getprotobyname("ipv6-icmp"); | ||
24 | /* if getprotobyname failed, just silently force | ||
25 | * proto->p_proto to have the correct value for "ipv6-icmp" */ | ||
26 | if ((sock = socket(AF_INET6, SOCK_RAW, | ||
27 | (proto ? proto->p_proto : IPPROTO_ICMPV6))) < 0) { | ||
28 | if (errno == EPERM) | ||
29 | error_msg_and_die("permission denied. (are you root?)"); | ||
30 | else | ||
31 | perror_msg_and_die(can_not_create_raw_socket); | ||
32 | } | ||
33 | |||
34 | /* drop root privs if running setuid */ | ||
35 | setuid(getuid()); | ||
36 | |||
37 | return sock; | ||
38 | } | ||
39 | #endif | ||
diff --git a/libbb/inet_common.c b/libbb/inet_common.c index c1e5953fe..c7bf409c4 100644 --- a/libbb/inet_common.c +++ b/libbb/inet_common.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * | 4 | * |
5 | * Heavily modified by Manuel Novoa III Mar 12, 2001 | 5 | * Heavily modified by Manuel Novoa III Mar 12, 2001 |
6 | * | 6 | * |
7 | * Version: $Id: inet_common.c,v 1.2 2002/06/06 12:11:55 andersen Exp $ | 7 | * Version: $Id: inet_common.c,v 1.3 2002/07/03 11:46:36 andersen Exp $ |
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
@@ -177,3 +177,65 @@ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, | |||
177 | 177 | ||
178 | return (0); | 178 | return (0); |
179 | } | 179 | } |
180 | |||
181 | #if CONFIG_FEATURE_IPV6 | ||
182 | |||
183 | int INET6_resolve(char *name, struct sockaddr_in6 *sin6) | ||
184 | { | ||
185 | struct addrinfo req, *ai; | ||
186 | int s; | ||
187 | |||
188 | memset (&req, '\0', sizeof req); | ||
189 | req.ai_family = AF_INET6; | ||
190 | if ((s = getaddrinfo(name, NULL, &req, &ai))) { | ||
191 | fprintf(stderr, "getaddrinfo: %s: %d\n", name, s); | ||
192 | return -1; | ||
193 | } | ||
194 | memcpy(sin6, ai->ai_addr, sizeof(struct sockaddr_in6)); | ||
195 | |||
196 | freeaddrinfo(ai); | ||
197 | |||
198 | return (0); | ||
199 | } | ||
200 | |||
201 | #ifndef IN6_IS_ADDR_UNSPECIFIED | ||
202 | #define IN6_IS_ADDR_UNSPECIFIED(a) \ | ||
203 | (((__u32 *) (a))[0] == 0 && ((__u32 *) (a))[1] == 0 && \ | ||
204 | ((__u32 *) (a))[2] == 0 && ((__u32 *) (a))[3] == 0) | ||
205 | #endif | ||
206 | |||
207 | |||
208 | int INET6_rresolve(char *name, size_t len, struct sockaddr_in6 *sin6, int numeric) | ||
209 | { | ||
210 | int s; | ||
211 | |||
212 | /* Grmpf. -FvK */ | ||
213 | if (sin6->sin6_family != AF_INET6) { | ||
214 | #ifdef DEBUG | ||
215 | fprintf(stderr, _("rresolve: unsupport address family %d !\n"), | ||
216 | sin6->sin6_family); | ||
217 | #endif | ||
218 | errno = EAFNOSUPPORT; | ||
219 | return (-1); | ||
220 | } | ||
221 | if (numeric & 0x7FFF) { | ||
222 | inet_ntop(AF_INET6, &sin6->sin6_addr, name, len); | ||
223 | return (0); | ||
224 | } | ||
225 | if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { | ||
226 | if (numeric & 0x8000) | ||
227 | strcpy(name, "default"); | ||
228 | else | ||
229 | strcpy(name, "*"); | ||
230 | return (0); | ||
231 | } | ||
232 | |||
233 | if ((s = getnameinfo((struct sockaddr *) sin6, sizeof(struct sockaddr_in6), | ||
234 | name, len , NULL, 0, 0))) { | ||
235 | fputs("getnameinfo failed\n", stderr); | ||
236 | return -1; | ||
237 | } | ||
238 | return (0); | ||
239 | } | ||
240 | |||
241 | #endif /* CONFIG_FEATURE_IPV6 */ | ||
diff --git a/libbb/interface.c b/libbb/interface.c index 9ecb81b9f..5800e0f6a 100644 --- a/libbb/interface.c +++ b/libbb/interface.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * that either displays or sets the characteristics of | 15 | * that either displays or sets the characteristics of |
16 | * one or more of the system's networking interfaces. | 16 | * one or more of the system's networking interfaces. |
17 | * | 17 | * |
18 | * Version: $Id: interface.c,v 1.7 2001/11/10 11:22:46 andersen Exp $ | 18 | * Version: $Id: interface.c,v 1.8 2002/07/03 11:46:36 andersen Exp $ |
19 | * | 19 | * |
20 | * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> | 20 | * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> |
21 | * and others. Copyright 1993 MicroWalt Corporation | 21 | * and others. Copyright 1993 MicroWalt Corporation |
@@ -52,6 +52,10 @@ | |||
52 | #undef HAVE_AFECONET | 52 | #undef HAVE_AFECONET |
53 | #undef HAVE_AFASH | 53 | #undef HAVE_AFASH |
54 | 54 | ||
55 | #if CONFIG_FEATURE_IPV6 | ||
56 | #define HAVE_AFINET6 1 | ||
57 | #endif | ||
58 | |||
55 | /* | 59 | /* |
56 | * | 60 | * |
57 | * Device Hardware types. | 61 | * Device Hardware types. |
@@ -77,6 +81,7 @@ | |||
77 | 81 | ||
78 | #define _(x) x | 82 | #define _(x) x |
79 | #define _PATH_PROCNET_DEV "/proc/net/dev" | 83 | #define _PATH_PROCNET_DEV "/proc/net/dev" |
84 | #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6" | ||
80 | #define new(p) ((p) = xcalloc(1,sizeof(*(p)))) | 85 | #define new(p) ((p) = xcalloc(1,sizeof(*(p)))) |
81 | #define KRELEASE(maj,min,patch) ((maj) * 65536 + (min)*256 + (patch)) | 86 | #define KRELEASE(maj,min,patch) ((maj) * 65536 + (min)*256 + (patch)) |
82 | 87 | ||
@@ -425,6 +430,76 @@ static struct aftype inet_aftype = | |||
425 | 430 | ||
426 | #endif /* HAVE_AFINET */ | 431 | #endif /* HAVE_AFINET */ |
427 | 432 | ||
433 | #if HAVE_AFINET6 | ||
434 | |||
435 | #ifdef KEEP_UNUSED | ||
436 | static void INET6_reserror(char *text) | ||
437 | { | ||
438 | herror(text); | ||
439 | } | ||
440 | |||
441 | /* Display an Internet socket address. */ | ||
442 | static char *INET6_print(unsigned char *ptr) | ||
443 | { | ||
444 | static char name[80]; | ||
445 | |||
446 | inet_ntop(AF_INET6, (struct in6_addr *) ptr, name, 80); | ||
447 | return name; | ||
448 | } | ||
449 | #endif /* KEEP_UNUSED */ | ||
450 | |||
451 | /* Display an Internet socket address. */ | ||
452 | /* dirty! struct sockaddr usually doesn't suffer for inet6 addresses, fst. */ | ||
453 | static char *INET6_sprint(struct sockaddr *sap, int numeric) | ||
454 | { | ||
455 | static char buff[128]; | ||
456 | |||
457 | if (sap->sa_family == 0xFFFF || sap->sa_family == 0) | ||
458 | return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); | ||
459 | if (INET6_rresolve(buff, sizeof(buff), (struct sockaddr_in6 *) sap, numeric) != 0) | ||
460 | return safe_strncpy(buff, _("[UNKNOWN]"), sizeof(buff)); | ||
461 | return (buff); | ||
462 | } | ||
463 | |||
464 | #ifdef KEEP_UNUSED | ||
465 | static int INET6_getsock(char *bufp, struct sockaddr *sap) | ||
466 | { | ||
467 | struct sockaddr_in6 *sin6; | ||
468 | |||
469 | sin6 = (struct sockaddr_in6 *) sap; | ||
470 | sin6->sin6_family = AF_INET6; | ||
471 | sin6->sin6_port = 0; | ||
472 | |||
473 | if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0) | ||
474 | return (-1); | ||
475 | |||
476 | return 16; /* ?;) */ | ||
477 | } | ||
478 | |||
479 | static int INET6_input(int type, char *bufp, struct sockaddr *sap) | ||
480 | { | ||
481 | switch (type) { | ||
482 | case 1: | ||
483 | return (INET6_getsock(bufp, sap)); | ||
484 | default: | ||
485 | return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap)); | ||
486 | } | ||
487 | } | ||
488 | #endif /* KEEP_UNUSED */ | ||
489 | |||
490 | static struct aftype inet6_aftype = | ||
491 | { | ||
492 | "inet6", "IPv6", AF_INET6, sizeof(struct in6_addr), | ||
493 | NULL /* UNUSED INET6_print */, INET6_sprint, | ||
494 | NULL /* UNUSED INET6_input */, NULL /* UNUSED INET6_reserror */, | ||
495 | NULL /*INET6_rprint */ , NULL /*INET6_rinput */ , | ||
496 | NULL /* UNUSED INET6_getnetmask */, | ||
497 | -1, | ||
498 | NULL | ||
499 | }; | ||
500 | |||
501 | #endif /* HAVE_AFINET6 */ | ||
502 | |||
428 | /* Display an UNSPEC address. */ | 503 | /* Display an UNSPEC address. */ |
429 | static char *UNSPEC_print(unsigned char *ptr) | 504 | static char *UNSPEC_print(unsigned char *ptr) |
430 | { | 505 | { |
@@ -1709,7 +1784,6 @@ static void ife_print(struct interface *ptr) | |||
1709 | char addr6[40], devname[20]; | 1784 | char addr6[40], devname[20]; |
1710 | struct sockaddr_in6 sap; | 1785 | struct sockaddr_in6 sap; |
1711 | int plen, scope, dad_status, if_idx; | 1786 | int plen, scope, dad_status, if_idx; |
1712 | extern struct aftype inet6_aftype; | ||
1713 | char addr6p[8][5]; | 1787 | char addr6p[8][5]; |
1714 | #endif | 1788 | #endif |
1715 | 1789 | ||
@@ -1756,8 +1830,24 @@ static void ife_print(struct interface *ptr) | |||
1756 | #endif | 1830 | #endif |
1757 | 1831 | ||
1758 | #if HAVE_AFINET6 | 1832 | #if HAVE_AFINET6 |
1759 | /* FIXME: should be integrated into interface.c. */ | ||
1760 | 1833 | ||
1834 | #define IPV6_ADDR_ANY 0x0000U | ||
1835 | |||
1836 | #define IPV6_ADDR_UNICAST 0x0001U | ||
1837 | #define IPV6_ADDR_MULTICAST 0x0002U | ||
1838 | #define IPV6_ADDR_ANYCAST 0x0004U | ||
1839 | |||
1840 | #define IPV6_ADDR_LOOPBACK 0x0010U | ||
1841 | #define IPV6_ADDR_LINKLOCAL 0x0020U | ||
1842 | #define IPV6_ADDR_SITELOCAL 0x0040U | ||
1843 | |||
1844 | #define IPV6_ADDR_COMPATv4 0x0080U | ||
1845 | |||
1846 | #define IPV6_ADDR_SCOPE_MASK 0x00f0U | ||
1847 | |||
1848 | #define IPV6_ADDR_MAPPED 0x1000U | ||
1849 | #define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */ | ||
1850 | |||
1761 | if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { | 1851 | if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { |
1762 | while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", | 1852 | while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", |
1763 | addr6p[0], addr6p[1], addr6p[2], addr6p[3], | 1853 | addr6p[0], addr6p[1], addr6p[2], addr6p[3], |
@@ -1767,11 +1857,12 @@ static void ife_print(struct interface *ptr) | |||
1767 | sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", | 1857 | sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", |
1768 | addr6p[0], addr6p[1], addr6p[2], addr6p[3], | 1858 | addr6p[0], addr6p[1], addr6p[2], addr6p[3], |
1769 | addr6p[4], addr6p[5], addr6p[6], addr6p[7]); | 1859 | addr6p[4], addr6p[5], addr6p[6], addr6p[7]); |
1770 | inet6_aftype.input(1, addr6, (struct sockaddr *) &sap); | 1860 | inet_pton(AF_INET6, addr6, (struct sockaddr *) &sap.sin6_addr); |
1861 | sap.sin6_family=AF_INET6; | ||
1771 | printf(_(" inet6 addr: %s/%d"), | 1862 | printf(_(" inet6 addr: %s/%d"), |
1772 | inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen); | 1863 | inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen); |
1773 | printf(_(" Scope:")); | 1864 | printf(_(" Scope:")); |
1774 | switch (scope) { | 1865 | switch (scope & IPV6_ADDR_SCOPE_MASK) { |
1775 | case 0: | 1866 | case 0: |
1776 | printf(_("Global")); | 1867 | printf(_("Global")); |
1777 | break; | 1868 | break; |
diff --git a/libbb/xgethostbyname2.c b/libbb/xgethostbyname2.c new file mode 100644 index 000000000..c66acfee1 --- /dev/null +++ b/libbb/xgethostbyname2.c | |||
@@ -0,0 +1,37 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Mini xgethostbyname2 implementation. | ||
4 | * | ||
5 | * Copyright (C) 2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <netdb.h> | ||
24 | #include "libbb.h" | ||
25 | |||
26 | |||
27 | #if CONFIG_FEATURE_IPV6 | ||
28 | struct hostent *xgethostbyname2(const char *name, int af) | ||
29 | { | ||
30 | struct hostent *retval; | ||
31 | |||
32 | if ((retval = gethostbyname2(name, af)) == NULL) | ||
33 | herror_msg_and_die("%s", name); | ||
34 | |||
35 | return retval; | ||
36 | } | ||
37 | #endif | ||