diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-07 01:24:12 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-07 01:24:12 +0000 |
| commit | fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a (patch) | |
| tree | 0d2f47866709f0a555d28166b4aeca04dfb7808c /networking/interface.c | |
| parent | b05955e0a5aa5c16ef9460cf4bfed1ee589f5f64 (diff) | |
| download | busybox-w32-fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a.tar.gz busybox-w32-fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a.tar.bz2 busybox-w32-fa85b86f388fb037b67fa7fcc3b5502c8d0fa84a.zip | |
add arp applet - thanks to
"Eric Spakman" <E.Spakman@inter.nl.net>
Diffstat (limited to 'networking/interface.c')
| -rw-r--r-- | networking/interface.c | 200 |
1 files changed, 165 insertions, 35 deletions
diff --git a/networking/interface.c b/networking/interface.c index b39298cfe..6d23e9bfc 100644 --- a/networking/interface.c +++ b/networking/interface.c | |||
| @@ -91,26 +91,6 @@ struct in6_ifreq { | |||
| 91 | #define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ | 91 | #define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ |
| 92 | #endif | 92 | #endif |
| 93 | 93 | ||
| 94 | /* This structure defines protocol families and their handlers. */ | ||
| 95 | struct aftype { | ||
| 96 | const char *name; | ||
| 97 | const char *title; | ||
| 98 | int af; | ||
| 99 | int alen; | ||
| 100 | char *(*print) (unsigned char *); | ||
| 101 | char *(*sprint) (struct sockaddr *, int numeric); | ||
| 102 | int (*input) (int type, char *bufp, struct sockaddr *); | ||
| 103 | void (*herror) (char *text); | ||
| 104 | int (*rprint) (int options); | ||
| 105 | int (*rinput) (int typ, int ext, char **argv); | ||
| 106 | |||
| 107 | /* may modify src */ | ||
| 108 | int (*getmask) (char *src, struct sockaddr * mask, char *name); | ||
| 109 | |||
| 110 | int fd; | ||
| 111 | char *flag_file; | ||
| 112 | }; | ||
| 113 | |||
| 114 | /* Display an Internet socket address. */ | 94 | /* Display an Internet socket address. */ |
| 115 | static char *INET_sprint(struct sockaddr *sap, int numeric) | 95 | static char *INET_sprint(struct sockaddr *sap, int numeric) |
| 116 | { | 96 | { |
| @@ -126,12 +106,66 @@ static char *INET_sprint(struct sockaddr *sap, int numeric) | |||
| 126 | return buff; | 106 | return buff; |
| 127 | } | 107 | } |
| 128 | 108 | ||
| 109 | static int INET_getsock(char *bufp, struct sockaddr *sap) | ||
| 110 | { | ||
| 111 | char *sp = bufp, *bp; | ||
| 112 | unsigned int i; | ||
| 113 | unsigned val; | ||
| 114 | struct sockaddr_in *sock_in; | ||
| 115 | |||
| 116 | sock_in = (struct sockaddr_in *) sap; | ||
| 117 | sock_in->sin_family = AF_INET; | ||
| 118 | sock_in->sin_port = 0; | ||
| 119 | |||
| 120 | val = 0; | ||
| 121 | bp = (char *) &val; | ||
| 122 | for (i = 0; i < sizeof(sock_in->sin_addr.s_addr); i++) { | ||
| 123 | *sp = toupper(*sp); | ||
| 124 | |||
| 125 | if ((unsigned)(*sp - 'A') <= 5) | ||
| 126 | bp[i] |= (int) (*sp - ('A' - 10)); | ||
| 127 | else if (isdigit(*sp)) | ||
| 128 | bp[i] |= (int) (*sp - '0'); | ||
| 129 | else | ||
| 130 | return -1; | ||
| 131 | |||
| 132 | bp[i] <<= 4; | ||
| 133 | sp++; | ||
| 134 | *sp = toupper(*sp); | ||
| 135 | |||
| 136 | if ((unsigned)(*sp - 'A') <= 5) | ||
| 137 | bp[i] |= (int) (*sp - ('A' - 10)); | ||
| 138 | else if (isdigit(*sp)) | ||
| 139 | bp[i] |= (int) (*sp - '0'); | ||
| 140 | else | ||
| 141 | return -1; | ||
| 142 | |||
| 143 | sp++; | ||
| 144 | } | ||
| 145 | sock_in->sin_addr.s_addr = htonl(val); | ||
| 146 | |||
| 147 | return (sp - bufp); | ||
| 148 | } | ||
| 149 | |||
| 150 | static int INET_input(int type, char *bufp, struct sockaddr *sap) | ||
| 151 | { | ||
| 152 | switch (type) { | ||
| 153 | case 1: | ||
| 154 | return (INET_getsock(bufp, sap)); | ||
| 155 | case 256: | ||
| 156 | return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1)); | ||
| 157 | default: | ||
| 158 | return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0)); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 129 | static struct aftype inet_aftype = { | 162 | static struct aftype inet_aftype = { |
| 130 | .name = "inet", | 163 | .name = "inet", |
| 131 | .title = "DARPA Internet", | 164 | .title = "DARPA Internet", |
| 132 | .af = AF_INET, | 165 | .af = AF_INET, |
| 133 | .alen = 4, | 166 | .alen = 4, |
| 134 | .sprint = INET_sprint, | 167 | .sprint = INET_sprint, |
| 168 | .input = INET_input, | ||
| 135 | .fd = -1 | 169 | .fd = -1 |
| 136 | }; | 170 | }; |
| 137 | 171 | ||
| @@ -151,12 +185,37 @@ static char *INET6_sprint(struct sockaddr *sap, int numeric) | |||
| 151 | return buff; | 185 | return buff; |
| 152 | } | 186 | } |
| 153 | 187 | ||
| 188 | static int INET6_getsock(char *bufp, struct sockaddr *sap) | ||
| 189 | { | ||
| 190 | struct sockaddr_in6 *sin6; | ||
| 191 | |||
| 192 | sin6 = (struct sockaddr_in6 *) sap; | ||
| 193 | sin6->sin6_family = AF_INET6; | ||
| 194 | sin6->sin6_port = 0; | ||
| 195 | |||
| 196 | if (inet_pton(AF_INET6, bufp, sin6->sin6_addr.s6_addr) <= 0) | ||
| 197 | return -1; | ||
| 198 | |||
| 199 | return 16; /* ?;) */ | ||
| 200 | } | ||
| 201 | |||
| 202 | static int INET6_input(int type, char *bufp, struct sockaddr *sap) | ||
| 203 | { | ||
| 204 | switch (type) { | ||
| 205 | case 1: | ||
| 206 | return (INET6_getsock(bufp, sap)); | ||
| 207 | default: | ||
| 208 | return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap)); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 154 | static struct aftype inet6_aftype = { | 212 | static struct aftype inet6_aftype = { |
| 155 | .name = "inet6", | 213 | .name = "inet6", |
| 156 | .title = "IPv6", | 214 | .title = "IPv6", |
| 157 | .af = AF_INET6, | 215 | .af = AF_INET6, |
| 158 | .alen = sizeof(struct in6_addr), | 216 | .alen = sizeof(struct in6_addr), |
| 159 | .sprint = INET6_sprint, | 217 | .sprint = INET6_sprint, |
| 218 | .input = INET6_input, | ||
| 160 | .fd = -1 | 219 | .fd = -1 |
| 161 | }; | 220 | }; |
| 162 | 221 | ||
| @@ -206,6 +265,20 @@ static struct aftype * const aftypes[] = { | |||
| 206 | }; | 265 | }; |
| 207 | 266 | ||
| 208 | /* Check our protocol family table for this family. */ | 267 | /* Check our protocol family table for this family. */ |
| 268 | struct aftype *get_aftype(const char *name) | ||
| 269 | { | ||
| 270 | struct aftype * const *afp; | ||
| 271 | |||
| 272 | afp = aftypes; | ||
| 273 | while (*afp != NULL) { | ||
| 274 | if (!strcmp((*afp)->name, name)) | ||
| 275 | return (*afp); | ||
| 276 | afp++; | ||
| 277 | } | ||
| 278 | return NULL; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* Check our protocol family table for this family. */ | ||
| 209 | static struct aftype *get_afntype(int af) | 282 | static struct aftype *get_afntype(int af) |
| 210 | { | 283 | { |
| 211 | struct aftype * const *afp; | 284 | struct aftype * const *afp; |
| @@ -714,18 +787,6 @@ static int do_if_fetch(struct interface *ife) | |||
| 714 | return 0; | 787 | return 0; |
| 715 | } | 788 | } |
| 716 | 789 | ||
| 717 | /* This structure defines hardware protocols and their handlers. */ | ||
| 718 | struct hwtype { | ||
| 719 | const char * const name; | ||
| 720 | const char *title; | ||
| 721 | int type; | ||
| 722 | int alen; | ||
| 723 | char *(*print) (unsigned char *); | ||
| 724 | int (*input) (char *, struct sockaddr *); | ||
| 725 | int (*activate) (int fd); | ||
| 726 | int suppress_null_addr; | ||
| 727 | }; | ||
| 728 | |||
| 729 | static const struct hwtype unspec_hwtype = { | 790 | static const struct hwtype unspec_hwtype = { |
| 730 | .name = "unspec", | 791 | .name = "unspec", |
| 731 | .title = "UNSPEC", | 792 | .title = "UNSPEC", |
| @@ -759,14 +820,69 @@ static char *pr_ether(unsigned char *ptr) | |||
| 759 | return buff; | 820 | return buff; |
| 760 | } | 821 | } |
| 761 | 822 | ||
| 762 | static const struct hwtype ether_hwtype = { | 823 | static int in_ether(char *bufp, struct sockaddr *sap); |
| 824 | |||
| 825 | static struct hwtype ether_hwtype = { | ||
| 763 | .name = "ether", | 826 | .name = "ether", |
| 764 | .title = "Ethernet", | 827 | .title = "Ethernet", |
| 765 | .type = ARPHRD_ETHER, | 828 | .type = ARPHRD_ETHER, |
| 766 | .alen = ETH_ALEN, | 829 | .alen = ETH_ALEN, |
| 767 | .print = pr_ether | 830 | .print = pr_ether, |
| 831 | .input = in_ether | ||
| 768 | }; | 832 | }; |
| 769 | 833 | ||
| 834 | static unsigned hexchar2int(char c) | ||
| 835 | { | ||
| 836 | if (isdigit(c)) | ||
| 837 | return c - '0'; | ||
| 838 | c &= ~0x20; /* a -> A */ | ||
| 839 | if ((unsigned)(c - 'A') <= 5) | ||
| 840 | return c - ('A' - 10); | ||
| 841 | return ~0U; | ||
| 842 | } | ||
| 843 | |||
| 844 | /* Input an Ethernet address and convert to binary. */ | ||
| 845 | static int in_ether(char *bufp, struct sockaddr *sap) | ||
| 846 | { | ||
| 847 | unsigned char *ptr; | ||
| 848 | char c, *orig; | ||
| 849 | int i; | ||
| 850 | unsigned val; | ||
| 851 | |||
| 852 | sap->sa_family = ether_hwtype.type; | ||
| 853 | ptr = sap->sa_data; | ||
| 854 | |||
| 855 | i = 0; | ||
| 856 | orig = bufp; | ||
| 857 | while ((*bufp != '\0') && (i < ETH_ALEN)) { | ||
| 858 | val = hexchar2int(*bufp++) * 0x10; | ||
| 859 | if (val > 0xff) { | ||
| 860 | errno = EINVAL; | ||
| 861 | return -1; | ||
| 862 | } | ||
| 863 | c = *bufp; | ||
| 864 | if (c == ':' || c == 0) | ||
| 865 | val >>= 4; | ||
| 866 | else { | ||
| 867 | val |= hexchar2int(c); | ||
| 868 | if (val > 0xff) { | ||
| 869 | errno = EINVAL; | ||
| 870 | return -1; | ||
| 871 | } | ||
| 872 | } | ||
| 873 | if (c != 0) | ||
| 874 | bufp++; | ||
| 875 | *ptr++ = (unsigned char) val; | ||
| 876 | i++; | ||
| 877 | |||
| 878 | /* We might get a semicolon here - not required. */ | ||
| 879 | if (*bufp == ':') { | ||
| 880 | bufp++; | ||
| 881 | } | ||
| 882 | } | ||
| 883 | return 0; | ||
| 884 | } | ||
| 885 | |||
| 770 | #include <net/if_arp.h> | 886 | #include <net/if_arp.h> |
| 771 | 887 | ||
| 772 | static const struct hwtype ppp_hwtype = { | 888 | static const struct hwtype ppp_hwtype = { |
| @@ -811,7 +927,21 @@ static const char * const if_port_text[] = { | |||
| 811 | #endif | 927 | #endif |
| 812 | 928 | ||
| 813 | /* Check our hardware type table for this type. */ | 929 | /* Check our hardware type table for this type. */ |
| 814 | static const struct hwtype *get_hwntype(int type) | 930 | const struct hwtype *get_hwtype(const char *name) |
| 931 | { | ||
| 932 | const struct hwtype * const *hwp; | ||
| 933 | |||
| 934 | hwp = hwtypes; | ||
| 935 | while (*hwp != NULL) { | ||
| 936 | if (!strcmp((*hwp)->name, name)) | ||
| 937 | return (*hwp); | ||
| 938 | hwp++; | ||
| 939 | } | ||
| 940 | return NULL; | ||
| 941 | } | ||
| 942 | |||
| 943 | /* Check our hardware type table for this type. */ | ||
| 944 | const struct hwtype *get_hwntype(int type) | ||
| 815 | { | 945 | { |
| 816 | const struct hwtype * const *hwp; | 946 | const struct hwtype * const *hwp; |
| 817 | 947 | ||
