📄 interface.c
字号:
/* * ifconfig This file contains an implementation of the command * that either displays or sets the characteristics of * one or more of the system's networking interfaces. * * Version: $Id$ * * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * and others. Copyright 1993 MicroWalt Corporation * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software * Foundation; either version 2 of the License, or (at * your option) any later version. * * Patched to support 'add' and 'del' keywords for INET(4) addresses * by Mrs. Brisby <mrs.brisby@nimh.org> * * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> * - gettext instead of catgets for i18n * 10/1998 - Andi Kleen. Use interface list primitives. * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu * (default AF was wrong) * stolen from net-tools-1.59 and stripped down for busybox by * Erik Andersen <andersee@debian.org> *//* * Heavily modified by Manuel Novoa III Mar 12, 2001 * * Pruned unused code using KEEP_UNUSED define. * Added print_bytes_scaled function to reduce code size. * Added some (potentially) missing defines. * Improved display support for -a and for a named interface. *//* #define KEEP_UNUSED */#include "busybox.h"/* * * Protocol Families. * */#define HAVE_AFINET 1#undef HAVE_AFINET6#undef HAVE_AFIPX#undef HAVE_AFATALK#undef HAVE_AFNETROM#undef HAVE_AFX25#undef HAVE_AFECONET/* * * Device Hardware types. * */#define HAVE_HWETHER 1#define HAVE_HWPPP 1#undef HAVE_HWSLIP#include <features.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <netinet/in.h>#include <net/if.h>#include <net/if_arp.h>#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/inet.h>#include <arpa/nameser.h>#define _(x) x#define _PATH_PROCNET_DEV "/proc/net/dev"#define new(p) ((p) = xcalloc(1,sizeof(*(p))))#define KRELEASE(maj,min,patch) ((maj) * 10000 + (min)*1000 + (patch))static int procnetdev_vsn = 1;/* Ugh. But libc5 doesn't provide POSIX types. */#include <asm/types.h>#ifdef HAVE_HWSLIP#include <linux/if_slip.h>#endif#if HAVE_AFINET6#ifndef _LINUX_IN6_H/* * This is in linux/include/net/ipv6.h. */struct in6_ifreq { struct in6_addr ifr6_addr; __u32 ifr6_prefixlen; unsigned int ifr6_ifindex;};#endif#endif /* HAVE_AFINET6 */#if HAVE_AFIPX#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)#include <netipx/ipx.h>#else#include "ipx.h"#endif#endif/* Defines for glibc2.0 users. */#ifndef SIOCSIFTXQLEN#define SIOCSIFTXQLEN 0x8943#define SIOCGIFTXQLEN 0x8942#endif/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */#ifndef ifr_qlen#define ifr_qlen ifr_ifru.ifru_mtu#endif#ifndef HAVE_TXQUEUELEN#define HAVE_TXQUEUELEN 1#endif#ifndef IFF_DYNAMIC#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */#endif/* This structure defines protocol families and their handlers. */struct aftype { const char *name; const char *title; int af; int alen; char *(*print) (unsigned char *); char *(*sprint) (struct sockaddr *, int numeric); int (*input) (int type, char *bufp, struct sockaddr *); void (*herror) (char *text); int (*rprint) (int options); int (*rinput) (int typ, int ext, char **argv); /* may modify src */ int (*getmask) (char *src, struct sockaddr * mask, char *name); int fd; char *flag_file;};static struct aftype *aftypes[];#ifdef KEEP_UNUSEDstatic int flag_unx;static int flag_ipx;static int flag_ax25;static int flag_ddp;static int flag_netrom;static int flag_inet;static int flag_inet6;static int flag_econet;static int flag_x25 = 0;static int flag_ash;static struct aftrans_t { char *alias; char *name; int *flag;} aftrans[] = { { "ax25", "ax25", &flag_ax25 }, { "ip", "inet", &flag_inet }, { "ip6", "inet6", &flag_inet6 }, { "ipx", "ipx", &flag_ipx }, { "appletalk", "ddp", &flag_ddp }, { "netrom", "netrom", &flag_netrom }, { "inet", "inet", &flag_inet }, { "inet6", "inet6", &flag_inet6 }, { "ddp", "ddp", &flag_ddp }, { "unix", "unix", &flag_unx }, { "tcpip", "inet", &flag_inet }, { "econet", "ec", &flag_econet }, { "x25", "x25", &flag_x25 }, { "ash", "ash", &flag_ash }, { 0, 0, 0 }};static char afname[256] = "";#endif /* KEEP_UNUSED */#if HAVE_AFUNIX/* Display a UNIX domain address. */static char *UNIX_print(unsigned char *ptr){ return (ptr);}/* Display a UNIX domain address. */static char *UNIX_sprint(struct sockaddr *sap, int numeric){ static char buf[64]; if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return safe_strncpy(buf, _("[NONE SET]"), sizeof(buf)); return (UNIX_print(sap->sa_data));}static struct aftype unix_aftype ={ "unix", "UNIX Domain", AF_UNIX, 0, UNIX_print, UNIX_sprint, NULL, NULL, NULL, NULL, NULL, -1, "/proc/net/unix"};#endif /* HAVE_AFUNIX */#if HAVE_AFINET/* cache */struct addr { struct sockaddr_in addr; char *name; int host; struct addr *next;};static struct addr *INET_nn = NULL; /* addr-to-name cache */#ifdef KEEP_UNUSEDstatic int INET_resolve(char *name, struct sockaddr_in *sin, int hostfirst){ struct hostent *hp; struct netent *np; /* Grmpf. -FvK */ sin->sin_family = AF_INET; sin->sin_port = 0; /* Default is special, meaning 0.0.0.0. */ if (!strcmp(name, "default")) { sin->sin_addr.s_addr = INADDR_ANY; return (1); } /* Look to see if it's a dotted quad. */ if (inet_aton(name, &sin->sin_addr)) { return 0; } /* If we expect this to be a hostname, try hostname database first */#ifdef DEBUG if (hostfirst) fprintf (stderr, "gethostbyname (%s)\n", name);#endif if (hostfirst && (hp = gethostbyname(name)) != (struct hostent *) NULL) { memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], sizeof(struct in_addr)); return 0; } /* Try the NETWORKS database to see if this is a known network. */#ifdef DEBUG fprintf (stderr, "getnetbyname (%s)\n", name);#endif if ((np = getnetbyname(name)) != (struct netent *) NULL) { sin->sin_addr.s_addr = htonl(np->n_net); return 1; } if (hostfirst) { /* Don't try again */ errno = h_errno; return -1; }#ifdef DEBUG res_init(); _res.options |= RES_DEBUG;#endif#ifdef DEBUG fprintf (stderr, "gethostbyname (%s)\n", name);#endif if ((hp = gethostbyname(name)) == (struct hostent *) NULL) { errno = h_errno; return -1; } memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], sizeof(struct in_addr)); return 0;}#endif /* KEEP_UNUSED *//* numeric: & 0x8000: default instead of *, * & 0x4000: host instead of net, * & 0x0fff: don't resolve */static int INET_rresolve(char *name, size_t len, struct sockaddr_in *sin, int numeric, unsigned int netmask){ struct hostent *ent; struct netent *np; struct addr *pn; unsigned long ad, host_ad; int host = 0; /* Grmpf. -FvK */ if (sin->sin_family != AF_INET) {#ifdef DEBUG fprintf(stderr, _("rresolve: unsupport address family %d !\n"), sin->sin_family);#endif errno = EAFNOSUPPORT; return (-1); } ad = (unsigned long) sin->sin_addr.s_addr;#ifdef DEBUG fprintf (stderr, "rresolve: %08lx, mask %08x, num %08x \n", ad, netmask, numeric);#endif if (ad == INADDR_ANY) { if ((numeric & 0x0FFF) == 0) { if (numeric & 0x8000) safe_strncpy(name, "default", len); else safe_strncpy(name, "*", len); return (0); } } if (numeric & 0x0FFF) { safe_strncpy(name, inet_ntoa(sin->sin_addr), len); return (0); } if ((ad & (~netmask)) != 0 || (numeric & 0x4000)) host = 1; pn = INET_nn; while (pn != NULL) { if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { safe_strncpy(name, pn->name, len);#ifdef DEBUG fprintf (stderr, "rresolve: found %s %08lx in cache\n", (host? "host": "net"), ad);#endif return (0); } pn = pn->next; } host_ad = ntohl(ad); np = NULL; ent = NULL; if (host) {#ifdef DEBUG fprintf (stderr, "gethostbyaddr (%08lx)\n", ad);#endif ent = gethostbyaddr((char *) &ad, 4, AF_INET); if (ent != NULL) safe_strncpy(name, ent->h_name, len); } else {#ifdef DEBUG fprintf (stderr, "getnetbyaddr (%08lx)\n", host_ad);#endif np = getnetbyaddr(host_ad, AF_INET); if (np != NULL) safe_strncpy(name, np->n_name, len); } if ((ent == NULL) && (np == NULL)) safe_strncpy(name, inet_ntoa(sin->sin_addr), len); pn = (struct addr *) xmalloc(sizeof(struct addr)); pn->addr = *sin; pn->next = INET_nn; pn->host = host; pn->name = (char *) xmalloc(strlen(name) + 1); strcpy(pn->name, name); INET_nn = pn; return (0);}#ifdef KEEP_UNUSEDstatic void INET_reserror(char *text){ herror(text);}/* Display an Internet socket address. */static char *INET_print(unsigned char *ptr){ return (inet_ntoa((*(struct in_addr *) ptr)));}#endif /* KEEP_UNUSED *//* Display an Internet socket address. */static char *INET_sprint(struct sockaddr *sap, int numeric){ static char buff[128]; if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap, numeric, 0xffffff00) != 0) return (NULL); return (buff);}#ifdef KEEP_UNUSEDstatic char *INET_sprintmask(struct sockaddr *sap, int numeric, unsigned int netmask){ static char buff[128]; if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap, numeric, netmask) != 0) return (NULL); return (buff);}static int INET_getsock(char *bufp, struct sockaddr *sap){ char *sp = bufp, *bp; unsigned int i; unsigned val; struct sockaddr_in *sin; sin = (struct sockaddr_in *) sap; sin->sin_family = AF_INET; sin->sin_port = 0; val = 0; bp = (char *) &val; for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) { *sp = toupper(*sp); if ((*sp >= 'A') && (*sp <= 'F')) bp[i] |= (int) (*sp - 'A') + 10; else if ((*sp >= '0') && (*sp <= '9')) bp[i] |= (int) (*sp - '0'); else return (-1); bp[i] <<= 4; sp++; *sp = toupper(*sp); if ((*sp >= 'A') && (*sp <= 'F')) bp[i] |= (int) (*sp - 'A') + 10; else if ((*sp >= '0') && (*sp <= '9')) bp[i] |= (int) (*sp - '0'); else return (-1); sp++; } sin->sin_addr.s_addr = htonl(val); return (sp - bufp);}static int INET_input(int type, char *bufp, struct sockaddr *sap){ switch (type) { case 1: return (INET_getsock(bufp, sap)); case 256: return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1)); default: return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0)); }}static int INET_getnetmask(char *adr, struct sockaddr *m, char *name){ struct sockaddr_in *mask = (struct sockaddr_in *) m; char *slash, *end; int prefix;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -