913 lines
20 KiB
C
913 lines
20 KiB
C
/*
|
|
* Copyright (c) 1983 Regents of the University of California.
|
|
* All rights reserved. The Berkeley software License Agreement
|
|
* specifies the terms and conditions for redistribution.
|
|
*
|
|
* @(#)ifconfig.c 1.1 94/10/31 SMI from UCB 4.18 5/22/86
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/file.h>
|
|
|
|
#include <netinet/in.h>
|
|
#include <net/if.h>
|
|
#include <netinet/if_ether.h>
|
|
|
|
#ifdef NS
|
|
#define NSIP
|
|
#include <netns/ns.h>
|
|
#include <netns/ns_if.h>
|
|
#endif
|
|
|
|
#ifdef APPLETALK
|
|
#include <netat/atalk.h>
|
|
#endif APPLETALK
|
|
|
|
#define NIT
|
|
#ifdef NIT
|
|
#include <sys/time.h>
|
|
#include <net/nit_if.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <netdb.h>
|
|
|
|
char *inet_ntoa();
|
|
|
|
struct ifreq ifr;
|
|
struct sockaddr_in sin = { AF_INET };
|
|
struct sockaddr_in broadaddr;
|
|
struct sockaddr_in netmask = { AF_INET };
|
|
struct sockaddr_in ipdst = { AF_INET };
|
|
char name[30];
|
|
int setaddr;
|
|
int setmask;
|
|
int setbroadaddr;
|
|
int setipdst;
|
|
int s;
|
|
|
|
void setifflags(), setifaddr(), setifdstaddr(), setifnetmask();
|
|
void setifmetric(), setifbroadaddr(), setifipdst(), setifether();
|
|
|
|
#define NEXTARG 0xffffff
|
|
#define AF_ANY (-1)
|
|
|
|
struct cmd {
|
|
char *c_name;
|
|
int c_parameter; /* NEXTARG means next argv */
|
|
void (*c_func)();
|
|
int c_af; /* address family restrictions */
|
|
} cmds[] = {
|
|
{ "up", IFF_UP, setifflags, AF_ANY } ,
|
|
{ "down", -IFF_UP, setifflags, AF_ANY },
|
|
{ "trailers", -IFF_NOTRAILERS,setifflags, AF_ANY },
|
|
{ "-trailers", IFF_NOTRAILERS, setifflags, AF_ANY },
|
|
{ "arp", -IFF_NOARP, setifflags, AF_ANY },
|
|
{ "-arp", IFF_NOARP, setifflags, AF_ANY },
|
|
{ "private", IFF_PRIVATE, setifflags, AF_ANY },
|
|
{ "-private", -IFF_PRIVATE, setifflags, AF_ANY },
|
|
{ "netmask", NEXTARG, setifnetmask, AF_INET },
|
|
{ "metric", NEXTARG, setifmetric, AF_ANY },
|
|
{ "broadcast", NEXTARG, setifbroadaddr, AF_ANY },
|
|
{ "ipdst", NEXTARG, setifipdst, AF_NS },
|
|
{ "ether", NEXTARG, setifether, AF_ANY },
|
|
{ 0, 0, setifaddr, AF_ANY },
|
|
{ 0, 0, setifdstaddr, AF_ANY },
|
|
};
|
|
|
|
/*
|
|
* XNS support liberally adapted from
|
|
* code written at the University of Maryland
|
|
* principally by James O'Toole and Chris Torek.
|
|
*/
|
|
|
|
int in_status(), in_getaddr();
|
|
int xns_status(), xns_getaddr();
|
|
int at_status(), at_getaddr();
|
|
int ether_status(), ether_getaddr();
|
|
|
|
/* Known address families */
|
|
struct afswtch {
|
|
char *af_name;
|
|
short af_af;
|
|
int (*af_status)();
|
|
int (*af_getaddr)();
|
|
} afs[] = {
|
|
{ "inet", AF_INET, in_status, in_getaddr },
|
|
{ "ns", AF_NS, xns_status, xns_getaddr },
|
|
{ "appletalk", AF_APPLETALK, at_status, at_getaddr },
|
|
{ "ether", AF_INET, ether_status, ether_getaddr },
|
|
{ 0, 0, 0, 0 }
|
|
};
|
|
|
|
struct afswtch *afp; /*the address family being set or asked about*/
|
|
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
int af = AF_INET;
|
|
void foreachinterface(), ifconfig();
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s\n",
|
|
"\t[ <af> ] [ <address> [ <dest_addr> ] ] [ up ] [ down ]\n",
|
|
"\t[ netmask <mask> ] [ broadcast <broad_addr> ]\n",
|
|
"\t[ metric <n> ]\n",
|
|
"\t[ trailers | -trailers ] [private | -private]\n",
|
|
"\t[ arp | -arp ] \n");
|
|
exit(1);
|
|
}
|
|
argc--, argv++;
|
|
strncpy(name, *argv, sizeof(name));
|
|
argc--, argv++;
|
|
if (argc > 0) {
|
|
struct afswtch *myafp;
|
|
|
|
for (myafp = afp = afs; myafp->af_name; myafp++)
|
|
if (strcmp(myafp->af_name, *argv) == 0) {
|
|
afp = myafp; argc--; argv++;
|
|
break;
|
|
}
|
|
af = ifr.ifr_addr.sa_family = afp->af_af;
|
|
}
|
|
s = socket(af, SOCK_DGRAM, 0);
|
|
if (s < 0) {
|
|
perror("ifconfig: socket");
|
|
exit(1);
|
|
}
|
|
if (strcmp(name, "-a"))
|
|
ifconfig(argc, argv, af, (struct ifnet *) NULL);
|
|
else
|
|
foreachinterface(ifconfig, argc, argv, af);
|
|
|
|
exit(0);
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
/*
|
|
* For each interface, call (*func)(argc, argv, af, ifrp).
|
|
*/
|
|
void
|
|
foreachinterface(func, argc, argv, af)
|
|
void (*func)();
|
|
int argc;
|
|
char **argv;
|
|
int af;
|
|
{
|
|
int n;
|
|
char buf[BUFSIZ];
|
|
struct ifconf ifc;
|
|
register struct ifreq *ifrp;
|
|
|
|
ifc.ifc_len = sizeof (buf);
|
|
ifc.ifc_buf = buf;
|
|
if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
|
|
perror("ioctl (get interface configuration)");
|
|
close(s);
|
|
return;
|
|
}
|
|
|
|
ifrp = ifc.ifc_req;
|
|
for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifrp++) {
|
|
/*
|
|
* We must close and recreate the socket each time
|
|
* since we don't know what type of socket it is now
|
|
* (each status function may change it).
|
|
*/
|
|
(void) close(s);
|
|
s = socket(af, SOCK_DGRAM, 0);
|
|
if (s == -1) {
|
|
perror("ifconfig: socket");
|
|
exit(1);
|
|
}
|
|
|
|
/*
|
|
* Reset global state variables to known values.
|
|
*/
|
|
setaddr = setbroadaddr = setipdst = setmask = 0;
|
|
(void) strncpy(name, ifrp->ifr_name, sizeof(name));
|
|
|
|
(*func)(argc, argv, af, ifrp);
|
|
}
|
|
}
|
|
|
|
void
|
|
ifconfig(argc, argv, af, ifrp)
|
|
int argc;
|
|
char **argv;
|
|
int af;
|
|
register struct ifreq *ifrp;
|
|
{
|
|
if (argc == 0) {
|
|
status();
|
|
return;
|
|
}
|
|
while (argc > 0) {
|
|
register struct cmd *p;
|
|
|
|
for (p = cmds; p->c_name; p++)
|
|
if (strcmp(*argv, p->c_name) == 0)
|
|
break;
|
|
if (p->c_name == 0 && setaddr)
|
|
p++; /* got src, do dst */
|
|
if (p->c_func) {
|
|
if (p->c_parameter == NEXTARG) {
|
|
argc--, argv++;
|
|
if (argc == 0) {
|
|
(void) fprintf(stderr,
|
|
"ifconfig: no argument for %s\n",
|
|
p->c_name);
|
|
exit(1);
|
|
}
|
|
/*
|
|
* Call the function if:
|
|
*
|
|
* there's no address family
|
|
* restriction
|
|
* OR
|
|
* we don't know the address yet
|
|
* (because we were called from
|
|
* main)
|
|
* OR
|
|
* there is a restriction and
|
|
* the address families match
|
|
*/
|
|
if ((p->c_af == AF_ANY) ||
|
|
(ifrp == (struct ifreq *) NULL) ||
|
|
(ifrp->ifr_addr.sa_family == p->c_af)
|
|
)
|
|
(*p->c_func)(*argv);
|
|
} else
|
|
if ((p->c_af == AF_ANY) ||
|
|
(ifrp == (struct ifreq *) NULL) ||
|
|
(ifrp->ifr_addr.sa_family == p->c_af)
|
|
)
|
|
(*p->c_func)(*argv, p->c_parameter);
|
|
}
|
|
argc--, argv++;
|
|
}
|
|
if ((setmask || setaddr) && (af == AF_INET) &&
|
|
netmask.sin_addr.s_addr != INADDR_ANY) {
|
|
/*
|
|
* If setting the address and not the mask,
|
|
* clear any existing mask and the kernel will then
|
|
* assign the default. If setting both,
|
|
* set the mask first, so the address will be
|
|
* interpreted correctly.
|
|
*/
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
ifr.ifr_addr = *(struct sockaddr *)&netmask;
|
|
if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0)
|
|
Perror("ioctl (SIOCSIFNETMASK)");
|
|
}
|
|
#ifdef NS
|
|
if (setipdst && af == AF_NS) {
|
|
struct nsip_req rq;
|
|
int size = sizeof(rq);
|
|
|
|
rq.rq_ns = *(struct sockaddr *) &sin;
|
|
rq.rq_ip = *(struct sockaddr *) &ipdst;
|
|
|
|
if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
|
|
Perror("Encapsulation Routing");
|
|
setaddr = 0;
|
|
}
|
|
#endif
|
|
if (setaddr) {
|
|
ifr.ifr_addr = *(struct sockaddr *) &sin;
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0)
|
|
Perror("ioctl (SIOCSIFADDR)");
|
|
}
|
|
if (setbroadaddr) {
|
|
ifr.ifr_addr = *(struct sockaddr *)&broadaddr;
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCSIFBRDADDR, (caddr_t)&ifr) < 0)
|
|
Perror("ioctl (SIOCSIFBRDADDR)");
|
|
}
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
void
|
|
setifaddr(addr, param)
|
|
char *addr;
|
|
short param;
|
|
{
|
|
/*
|
|
* Delay the ioctl to set the interface addr until flags are all set.
|
|
* The address interpretation may depend on the flags,
|
|
* and the flags may change when the address is set.
|
|
*/
|
|
setaddr++;
|
|
(*afp->af_getaddr)(addr, &sin);
|
|
}
|
|
|
|
void
|
|
setifnetmask(addr)
|
|
char *addr;
|
|
{
|
|
if (strcmp(addr, "+") == 0) {
|
|
setmask = in_getmask( &netmask);
|
|
return;
|
|
}
|
|
in_getaddr(addr, &netmask);
|
|
setmask++;
|
|
}
|
|
|
|
void
|
|
setifbroadaddr(addr)
|
|
char *addr;
|
|
{
|
|
/*
|
|
* This doesn't set the broadcast address at all. Rather, it
|
|
* gets, then sets the interface's address, relying on the fact
|
|
* that resetting the address will reset the broadcast address.
|
|
*/
|
|
if (strcmp(addr, "+") == 0) {
|
|
if (!setaddr) {
|
|
/*
|
|
* If we do not already have an address to set,
|
|
* then we just read the interface to see if it
|
|
* is already set.
|
|
*/
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno != EADDRNOTAVAIL)
|
|
perror("SIOCGIFADDR failed - cannot reset broadcast address");
|
|
return;
|
|
}
|
|
sin = * ( (struct sockaddr_in *)&ifr.ifr_addr);
|
|
setaddr++;
|
|
|
|
}
|
|
/*
|
|
* Turn off setbraodcast to allow for the (rare)
|
|
* case of a user saying
|
|
* ifconfig ... broadcast <number> ... broadcast +
|
|
*/
|
|
setbroadaddr = 0;
|
|
return;
|
|
}
|
|
(*afp->af_getaddr)(addr, &broadaddr);
|
|
setbroadaddr++;
|
|
}
|
|
|
|
void
|
|
setifipdst(addr)
|
|
char *addr;
|
|
{
|
|
in_getaddr(addr, &ipdst);
|
|
setipdst++;
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
void
|
|
setifdstaddr(addr, param)
|
|
char *addr;
|
|
int param;
|
|
{
|
|
|
|
(*afp->af_getaddr)(addr, &ifr.ifr_addr);
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0)
|
|
Perror("ioctl (SIOCSIFDSTADDR)");
|
|
}
|
|
|
|
void
|
|
setifflags(vname, value)
|
|
char *vname;
|
|
int value;
|
|
{
|
|
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
|
|
Perror("ioctl (SIOCGIFFLAGS)");
|
|
if (value < 0) {
|
|
value = -value;
|
|
ifr.ifr_flags &= ~value;
|
|
} else
|
|
ifr.ifr_flags |= value;
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
|
|
Perror(vname);
|
|
}
|
|
|
|
void
|
|
setifmetric(val)
|
|
char *val;
|
|
{
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
ifr.ifr_metric = atoi(val);
|
|
if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
|
|
perror("ioctl (set metric)");
|
|
}
|
|
|
|
void
|
|
setifether(addr)
|
|
char *addr;
|
|
{
|
|
#ifdef NIT
|
|
int t;
|
|
struct ether_addr *ea, *ether_aton();
|
|
|
|
t = open("/dev/nit", O_RDONLY);
|
|
if (t == -1) {
|
|
perror("/dev/nit");
|
|
exit(1);
|
|
}
|
|
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
|
|
if (ioctl(t, NIOCBIND, (caddr_t) &ifr) < 0) {
|
|
perror("ioctl: NIOCBIND");
|
|
exit(1);
|
|
}
|
|
ea = ether_aton(addr);
|
|
(void) bcopy((caddr_t) ifr.ifr_addr.sa_data, ea, sizeof(struct ether_addr));
|
|
if (ioctl(t, SIOCSIFADDR, (caddr_t)&ifr) == -1) {
|
|
perror("ioctl (SIOCSIFADDR)");
|
|
}
|
|
(void) close(t);
|
|
#endif /* NIT */
|
|
}
|
|
|
|
#define IFFBITS \
|
|
"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\11PROMISC\12MULTI\020PRIVATE"
|
|
|
|
/*
|
|
* Print the status of the interface. If an address family was
|
|
* specified, show it and it only; otherwise, show them all.
|
|
*/
|
|
status()
|
|
{
|
|
register struct afswtch *p = afp;
|
|
short af = ifr.ifr_addr.sa_family;
|
|
register int flags;
|
|
|
|
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
|
|
Perror("ioctl (SIOCGIFFLAGS)");
|
|
exit(1);
|
|
}
|
|
flags = ifr.ifr_flags;
|
|
printf("%s: ", name);
|
|
printb("flags", flags, IFFBITS);
|
|
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
|
|
if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
|
|
perror("ioctl (SIOCGIFMETRIC)");
|
|
else {
|
|
if (ifr.ifr_metric)
|
|
printf(" metric %d", ifr.ifr_metric);
|
|
}
|
|
putchar('\n');
|
|
if ((p = afp) != NULL) {
|
|
(*p->af_status)(1, flags);
|
|
} else for (p = afs; p->af_name; p++) {
|
|
ifr.ifr_addr.sa_family = p->af_af;
|
|
(*p->af_status)(0, flags);
|
|
}
|
|
}
|
|
|
|
in_status(force, flags)
|
|
int force;
|
|
int flags;
|
|
{
|
|
struct sockaddr_in *sin;
|
|
char *inet_ntoa();
|
|
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
|
|
if (!force)
|
|
return;
|
|
bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
|
|
} else
|
|
Perror("ioctl (SIOCGIFADDR)");
|
|
}
|
|
sin = (struct sockaddr_in *)&ifr.ifr_addr;
|
|
printf("\tinet %s ", inet_ntoa(sin->sin_addr));
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
|
|
if (errno != EADDRNOTAVAIL)
|
|
perror("ioctl (SIOCGIFNETMASK)");
|
|
bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
|
|
} else
|
|
netmask.sin_addr =
|
|
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
|
|
if (flags & IFF_POINTOPOINT) {
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno == EADDRNOTAVAIL)
|
|
bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
|
|
else
|
|
perror("ioctl (SIOCGIFDSTADDR)");
|
|
}
|
|
sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
|
|
printf("--> %s ", inet_ntoa(sin->sin_addr));
|
|
}
|
|
printf("netmask %x ", ntohl(netmask.sin_addr.s_addr));
|
|
if (flags & IFF_BROADCAST) {
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno == EADDRNOTAVAIL)
|
|
bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
|
|
else
|
|
perror("ioctl (SIOCGIFADDR)");
|
|
}
|
|
sin = (struct sockaddr_in *)&ifr.ifr_addr;
|
|
if (sin->sin_addr.s_addr != 0)
|
|
printf("broadcast %s", inet_ntoa(sin->sin_addr));
|
|
}
|
|
putchar('\n');
|
|
}
|
|
|
|
|
|
xns_status(force, flags)
|
|
int force;
|
|
int flags;
|
|
{
|
|
#ifdef NS
|
|
struct sockaddr_ns *sns;
|
|
|
|
close(s);
|
|
s = socket(AF_NS, SOCK_DGRAM, 0);
|
|
if (s < 0) {
|
|
if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
|
|
return;
|
|
perror("ifconfig: ns socket");
|
|
exit(1);
|
|
}
|
|
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
|
|
if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
|
|
if (!force)
|
|
return;
|
|
bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
|
|
} else
|
|
perror("ioctl (SIOCGIFADDR)");
|
|
}
|
|
sns = (struct sockaddr_ns *)&ifr.ifr_addr;
|
|
printf("\tns %s ", ns_ntoa(sns->sns_addr));
|
|
if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
|
|
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
|
|
if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno == EADDRNOTAVAIL)
|
|
bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
|
|
else
|
|
Perror("ioctl (SIOCGIFDSTADDR)");
|
|
}
|
|
sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
|
|
printf("--> %s ", ns_ntoa(sns->sns_addr));
|
|
}
|
|
putchar('\n');
|
|
#endif
|
|
}
|
|
|
|
#ifdef APPLETALK
|
|
char *
|
|
at_ntoa(sad)
|
|
struct a_addr sad;
|
|
{
|
|
static char buf[256];
|
|
(void) sprintf( buf, "%d.%d", sad.at_Net, sad.at_Node);
|
|
return(buf);
|
|
}
|
|
#endif AAPLETALK
|
|
|
|
at_status(force, flags)
|
|
int force;
|
|
int flags;
|
|
{
|
|
#ifdef APPLETALK
|
|
struct sockaddr_at *sat;
|
|
|
|
close(s);
|
|
s = socket(AF_APPLETALK, SOCK_DGRAM, 0);
|
|
if (s < 0) {
|
|
if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
|
|
return;
|
|
perror("ifconfig: appletalk socket");
|
|
exit(1);
|
|
}
|
|
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
|
|
if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
|
|
if (!force)
|
|
return;
|
|
bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
|
|
} else
|
|
perror("ioctl (SIOCGIFADDR)");
|
|
}
|
|
sat = (struct sockaddr_at *)&ifr.ifr_addr;
|
|
printf("\tappletalk %s ", at_ntoa(sat->at_addr));
|
|
if (flags & IFF_POINTOPOINT) {
|
|
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
|
|
if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno == EADDRNOTAVAIL)
|
|
bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
|
|
else
|
|
Perror("ioctl (SIOCGIFDSTADDR)");
|
|
}
|
|
sat = (struct sockaddr_at *)&ifr.ifr_dstaddr;
|
|
printf("--> %s ", at_ntoa(sat->at_addr));
|
|
}
|
|
putchar('\n');
|
|
#endif APPLETALK
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
ether_status(force, flags)
|
|
int force;
|
|
int flags;
|
|
{
|
|
#ifdef NIT
|
|
register struct sockaddr *saddr;
|
|
char *ether_ntoa();
|
|
|
|
if (getuid())
|
|
return;
|
|
(void) close(s);
|
|
s = open("/dev/nit", O_RDONLY);
|
|
if (s == -1)
|
|
if (force) {
|
|
perror("/dev/nit");
|
|
exit(1);
|
|
}
|
|
else
|
|
return;
|
|
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
|
|
if (ioctl(s, NIOCBIND, (caddr_t) &ifr) < 0) {
|
|
perror("ioctl: NIOCBIND");
|
|
exit(1);
|
|
}
|
|
if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno == EINVAL)
|
|
return;
|
|
else
|
|
perror("ioctl (SIOCGIFADDR)");
|
|
}
|
|
saddr = (struct sockaddr *)&ifr.ifr_addr;
|
|
printf("\tether %s ", ether_ntoa((struct ether_addr *) saddr->sa_data));
|
|
putchar('\n');
|
|
#endif /* NIT */
|
|
}
|
|
|
|
Perror(cmd)
|
|
char *cmd;
|
|
{
|
|
extern int errno;
|
|
|
|
fprintf(stderr, "ifconfig: ");
|
|
switch (errno) {
|
|
|
|
case ENXIO:
|
|
fprintf(stderr, "%s: no such interface\n", cmd);
|
|
break;
|
|
|
|
case EPERM:
|
|
fprintf(stderr, "%s: permission denied\n", cmd);
|
|
break;
|
|
|
|
default:
|
|
perror(cmd);
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
struct in_addr inet_makeaddr();
|
|
|
|
in_getaddr(s, saddr)
|
|
char *s;
|
|
struct sockaddr *saddr;
|
|
{
|
|
register struct sockaddr_in *sin = (struct sockaddr_in *)saddr;
|
|
struct hostent *hp;
|
|
struct netent *np;
|
|
int val;
|
|
|
|
bzero((char *)saddr, sizeof *saddr);
|
|
sin->sin_family = AF_INET;
|
|
|
|
/*
|
|
* Try to catch attempts to set the broadcast address to all 1's.
|
|
*/
|
|
if (strcmp(s,"255.255.255.255") == 0 ||
|
|
((u_int) strtol(s, (char **) NULL, 0) == (u_int) 0xffffffff)) {
|
|
sin->sin_addr.s_addr = 0xffffffff;
|
|
return;
|
|
}
|
|
|
|
val = inet_addr(s);
|
|
if (val != -1) {
|
|
sin->sin_addr.s_addr = val;
|
|
return;
|
|
}
|
|
hp = gethostbyname(s);
|
|
if (hp) {
|
|
sin->sin_family = hp->h_addrtype;
|
|
bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
|
|
return;
|
|
}
|
|
np = getnetbyname(s);
|
|
if (np) {
|
|
sin->sin_family = np->n_addrtype;
|
|
sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
|
|
return;
|
|
}
|
|
fprintf(stderr, "ifconfig: %s: bad address\n", s);
|
|
exit(1);
|
|
}
|
|
|
|
/*
|
|
* Print a value a la the %b format of the kernel's printf
|
|
*/
|
|
printb(s, v, bits)
|
|
char *s;
|
|
register char *bits;
|
|
register unsigned short v;
|
|
{
|
|
register int i, any = 0;
|
|
register char c;
|
|
|
|
if (bits && *bits == 8)
|
|
printf("%s=%o", s, v);
|
|
else
|
|
printf("%s=%x", s, v);
|
|
bits++;
|
|
if (bits) {
|
|
putchar('<');
|
|
while (i = *bits++) {
|
|
if (v & (1 << (i-1))) {
|
|
if (any)
|
|
putchar(',');
|
|
any = 1;
|
|
for (; (c = *bits) > 32; bits++)
|
|
putchar(c);
|
|
} else
|
|
for (; *bits > 32; bits++)
|
|
;
|
|
}
|
|
putchar('>');
|
|
}
|
|
}
|
|
|
|
xns_getaddr(addr, saddr)
|
|
char *addr;
|
|
struct sockaddr *saddr;
|
|
{
|
|
#ifdef NS
|
|
struct sockaddr_ns *sns = (struct sockaddr_ns *)saddr;
|
|
struct ns_addr ns_addr();
|
|
|
|
bzero((char *)saddr, sizeof *saddr);
|
|
sns->sns_family = AF_NS;
|
|
sns->sns_addr = ns_addr(addr);
|
|
#endif
|
|
}
|
|
|
|
at_getaddr(addr, saddr)
|
|
char *addr;
|
|
struct sockaddr *saddr;
|
|
{
|
|
# ifdef APPLETALK
|
|
struct sockaddr_at *sat = (struct sockaddr_at *)saddr;
|
|
|
|
bzero((char *)saddr, sizeof *saddr);
|
|
sat->at_family = AF_APPLETALK;
|
|
sat->at_addr.at_Net = atoi(addr);
|
|
# endif APPLETALK
|
|
}
|
|
|
|
extern struct ether_addr *ether_aton();
|
|
|
|
ether_getaddr(addr, saddr)
|
|
char *addr;
|
|
struct sockaddr *saddr;
|
|
{
|
|
struct ether_addr *eaddr;
|
|
|
|
bzero((char *)saddr, sizeof *saddr);
|
|
saddr->sa_family = AF_UNSPEC;
|
|
/*
|
|
* call the library routine to do the conversion.
|
|
*/
|
|
eaddr = ether_aton(addr);
|
|
if (eaddr == NULL) {
|
|
fprintf(stderr, "ifconfig: %s: bad address\n", addr);
|
|
exit(1);
|
|
}
|
|
bcopy(eaddr, saddr->sa_data, sizeof(struct ether_addr));
|
|
}
|
|
|
|
# include <rpcsvc/ypclnt.h>
|
|
|
|
/*
|
|
* get the appropriate network mask entry given an address
|
|
*/
|
|
char *
|
|
getmaskbyaddr(netname)
|
|
char *netname;
|
|
{
|
|
static char *ypDomain = NULL;
|
|
char *out, *strtok();
|
|
int keylen, outsize, stat;
|
|
FILE *f;
|
|
static char line[1024];
|
|
|
|
if (ypDomain == NULL)
|
|
yp_get_default_domain(&ypDomain);
|
|
if (ypDomain != NULL) {
|
|
keylen = strlen(netname);
|
|
stat = yp_match(ypDomain, "netmasks.byaddr",
|
|
netname, keylen, &out, &outsize);
|
|
if (stat == 0)
|
|
return(out);
|
|
if (stat == YPERR_KEY)
|
|
return(0);
|
|
}
|
|
/*
|
|
* NIS did not work - read the local file
|
|
*/
|
|
f = fopen("/etc/netmasks", "r");
|
|
if (f == NULL)
|
|
return(0);
|
|
while (fgets(line, sizeof(line)-1, f)) {
|
|
out = strtok(line, " \t\n");
|
|
if (strcmp(line,netname) == 0) {
|
|
out = strtok(NULL, " \t\n");
|
|
return(out);
|
|
}
|
|
}
|
|
fclose(f);
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Look in the NIS for the network mask.
|
|
* returns true if we found one to set.
|
|
*/
|
|
in_getmask(saddr)
|
|
struct sockaddr_in *saddr;
|
|
{
|
|
char *out;
|
|
u_char *bytes;
|
|
int val;
|
|
char key[128];
|
|
struct in_addr net;
|
|
u_long i;
|
|
|
|
if (!setaddr) {
|
|
/*
|
|
* If we do not already have an address to set, then we just
|
|
* read the interface to see if it is already set.
|
|
*/
|
|
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
|
|
if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
|
|
if (errno != EADDRNOTAVAIL)
|
|
printf("Need net number for mask\n");
|
|
return(0);
|
|
}
|
|
sin = * ( (struct sockaddr_in *)&ifr.ifr_addr);
|
|
}
|
|
i = ntohl(sin.sin_addr.s_addr);
|
|
bytes = (u_char *)(&net);
|
|
if (IN_CLASSA(i)) {
|
|
net.s_addr = htonl(i & IN_CLASSA_NET);
|
|
sprintf(key, "%d", bytes[0]);
|
|
}
|
|
else if (IN_CLASSB(i)) {
|
|
net.s_addr = htonl(i & IN_CLASSB_NET);
|
|
sprintf(key, "%d.%d", bytes[0], bytes[1]);
|
|
}
|
|
else {
|
|
net.s_addr = htonl(i & IN_CLASSC_NET);
|
|
sprintf(key, "%d.%d.%d", bytes[0], bytes[1], bytes[2]);
|
|
}
|
|
out = getmaskbyaddr(key);
|
|
if (out == NULL) {
|
|
/*
|
|
* If at first not found, try unshifted too
|
|
*/
|
|
strcpy( key, inet_ntoa(net));
|
|
out = getmaskbyaddr(key);
|
|
if (out == NULL) {
|
|
saddr->sin_addr.s_addr = INADDR_ANY;
|
|
return(0);
|
|
}
|
|
}
|
|
val = (int)inet_addr(out);
|
|
if (val == -1) {
|
|
printf("Invalid netmask for %s: %s\n", key, out);
|
|
return(0);
|
|
}
|
|
saddr->sin_family = AF_INET;
|
|
saddr->sin_addr.s_addr = val;
|
|
printf("Setting netmask of %s to %s\n", name,
|
|
inet_ntoa(saddr->sin_addr) );
|
|
return(1);
|
|
}
|