ifconfig.c revision 8871
1/*
2 * Copyright (c) 1983, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char copyright[] =
36"@(#) Copyright (c) 1983, 1993\n\
37	The Regents of the University of California.  All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)ifconfig.c	8.2 (Berkeley) 2/16/94";
42#endif /* not lint */
43
44#include <sys/param.h>
45#include <sys/socket.h>
46#include <sys/ioctl.h>
47
48#include <net/if.h>
49#include <net/if_dl.h>
50#include <netinet/in.h>
51#include <netinet/in_var.h>
52#include <arpa/inet.h>
53
54#define	NSIP
55#include <netns/ns.h>
56#include <netns/ns_if.h>
57#include <netdb.h>
58
59#define EON
60#include <netiso/iso.h>
61#include <netiso/iso_var.h>
62#include <sys/protosw.h>
63
64#include <ctype.h>
65#include <err.h>
66#include <errno.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <unistd.h>
71#include <nlist.h>
72#include <kvm.h>
73#include <fcntl.h>
74
75struct	ifreq		ifr, ridreq;
76struct	ifaliasreq	addreq;
77struct	iso_ifreq	iso_ridreq;
78struct	iso_aliasreq	iso_addreq;
79struct	sockaddr_in	netmask;
80
81char	name[30];
82int	flags;
83int	metric;
84int	mtu;
85int	nsellength = 1;
86int	setaddr;
87int	setipdst;
88int	doalias;
89int	clearaddr;
90int	newaddr = 1;
91int	s;
92kvm_t	*kvmd;
93extern	int errno;
94
95int	setifflags(), setifaddr(), setifdstaddr(), setifnetmask();
96int	setifmetric(), setifmtu(), setifbroadaddr(), setifipdst();
97int	notealias(), setsnpaoffset(), setnsellength(), notrailers();
98
99#define	NEXTARG		0xffffff
100
101struct	cmd {
102	char	*c_name;
103	int	c_parameter;		/* NEXTARG means next argv */
104	int	(*c_func)();
105} cmds[] = {
106	{ "up",		IFF_UP,		setifflags } ,
107	{ "down",	-IFF_UP,	setifflags },
108	{ "trailers",	-1,		notrailers },
109	{ "-trailers",	1,		notrailers },
110	{ "arp",	-IFF_NOARP,	setifflags },
111	{ "-arp",	IFF_NOARP,	setifflags },
112	{ "debug",	IFF_DEBUG,	setifflags },
113	{ "-debug",	-IFF_DEBUG,	setifflags },
114	{ "alias",	IFF_UP,		notealias },
115	{ "-alias",	-IFF_UP,	notealias },
116	{ "delete",	-IFF_UP,	notealias },
117#ifdef notdef
118#define	EN_SWABIPS	0x1000
119	{ "swabips",	EN_SWABIPS,	setifflags },
120	{ "-swabips",	-EN_SWABIPS,	setifflags },
121#endif
122	{ "netmask",	NEXTARG,	setifnetmask },
123	{ "metric",	NEXTARG,	setifmetric },
124	{ "broadcast",	NEXTARG,	setifbroadaddr },
125	{ "ipdst",	NEXTARG,	setifipdst },
126	{ "snpaoffset",	NEXTARG,	setsnpaoffset },
127	{ "nsellength",	NEXTARG,	setnsellength },
128	{ "link0",	IFF_LINK0,	setifflags },
129	{ "-link0",	-IFF_LINK0,	setifflags },
130	{ "link1",	IFF_LINK1,	setifflags },
131	{ "-link1",	-IFF_LINK1,	setifflags },
132	{ "link2",	IFF_LINK2,	setifflags },
133	{ "-link2",	-IFF_LINK2,	setifflags },
134	{ "normal",	-IFF_LINK0,	setifflags },
135	{ "compress",	IFF_LINK0,	setifflags },
136	{ "noicmp",	IFF_LINK1,	setifflags },
137	{ "mtu",	NEXTARG,	setifmtu },
138	{ 0,		0,		setifaddr },
139	{ 0,		0,		setifdstaddr },
140};
141
142/*
143 * XNS support liberally adapted from code written at the University of
144 * Maryland principally by James O'Toole and Chris Torek.
145 */
146int	in_status(), in_getaddr();
147int	xns_status(), xns_getaddr();
148int	iso_status(), iso_getaddr();
149int	ether_status();
150
151/* Known address families */
152struct afswtch {
153	char *af_name;
154	short af_af;
155	int (*af_status)();
156	int (*af_getaddr)();
157	int af_difaddr;
158	int af_aifaddr;
159	caddr_t af_ridreq;
160	caddr_t af_addreq;
161} afs[] = {
162#define C(x) ((caddr_t) &x)
163	{ "inet", AF_INET, in_status, in_getaddr,
164	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
165	{ "ns", AF_NS, xns_status, xns_getaddr,
166	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
167	{ "iso", AF_ISO, iso_status, iso_getaddr,
168	     SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) },
169	{ "ether", AF_INET, ether_status, NULL },
170	{ 0,	0,	    0,		0 }
171};
172
173struct afswtch *afp;	/*the address family being set or asked about*/
174
175main(argc, argv)
176	int argc;
177	char *argv[];
178{
179	int af = AF_INET;
180	register struct afswtch *rafp;
181
182	if (argc < 2) {
183		fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s%s",
184		    "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]",
185			    "[ netmask mask ] ]\n",
186		    "\t[ metric n ]\n",
187		    "\t[ mtu n ]\n",
188		    "\t[ arp | -arp ]\n",
189		    "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ] \n");
190		exit(1);
191	}
192	argc--, argv++;
193	strncpy(name, *argv, sizeof(name));
194	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
195	argc--, argv++;
196	if (argc > 0) {
197		for (afp = rafp = afs; rafp->af_name; rafp++)
198			if (strcmp(rafp->af_name, *argv) == 0) {
199				afp = rafp; argc--; argv++;
200				break;
201			}
202		rafp = afp;
203		af = ifr.ifr_addr.sa_family = rafp->af_af;
204	}
205	s = socket(af, SOCK_DGRAM, 0);
206	if (s < 0) {
207		perror("ifconfig: socket");
208		exit(1);
209	}
210	if (strstr(name, "-a")) {
211		struct ifconf ifc;
212#define MAX_INTERFACES 50	/* Yeah right. */
213		char buffer[MAX_INTERFACES * sizeof(struct ifreq)];
214		struct ifreq *ifptr, *end;
215		int ifflags, selectflag = -1;
216
217		if (strstr(name, "-au"))
218			selectflag = 1;
219		if (strstr(name, "-ad"))
220			selectflag = 0;
221		ifc.ifc_len = sizeof(buffer);
222		ifc.ifc_buf = buffer;
223		if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) {
224			perror("ifconfig (SIOCGIFCONF)");
225			exit (1);
226		}
227		ifflags = ifc.ifc_req->ifr_flags;
228		end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
229		ifptr = ifc.ifc_req;
230		while (ifptr < end) {
231			sprintf(ifr.ifr_name,"%s",ifptr->ifr_name);
232			sprintf(name,"%s",ifptr->ifr_name);
233			close(s);
234			if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
235				perror("ifconfig: socket");
236				exit(1);
237			}
238			if (ifptr->ifr_flags == ifflags)
239				ifconfig(argc,argv,af,rafp,selectflag);
240			if(ifptr->ifr_addr.sa_len)	/* Dohw! */
241				ifptr = (struct ifreq *) ((caddr_t) ifptr +
242				ifptr->ifr_addr.sa_len -
243				sizeof(struct sockaddr));
244			ifptr++;
245		}
246	} else
247		ifconfig(argc,argv,af,rafp, -1);
248
249	exit (0);
250}
251
252
253
254ifconfig(argc,argv,af,rafp,flag)
255	int argc;
256	char *argv[];
257	int af;
258	struct afswtch *rafp;
259	int flag;
260{
261	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
262		Perror("ioctl (SIOCGIFFLAGS)");
263		exit(1);
264	}
265
266	switch(flag) {
267	case 0:
268		if (ifr.ifr_flags & IFF_UP)
269			return(0);
270		break;
271	case 1:
272		if (!(ifr.ifr_flags & IFF_UP))
273			return(0);
274		break;
275	case -1:
276	default:
277		break;
278	}
279
280	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
281	flags = ifr.ifr_flags;
282	if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
283		perror("ioctl (SIOCGIFMETRIC)");
284	else
285		metric = ifr.ifr_metric;
286	if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
287		perror("ioctl (SIOCGIFMTU)");
288	else
289		mtu = ifr.ifr_mtu;
290	if (argc == 0) {
291		status();
292		return(0);
293	}
294	while (argc > 0) {
295		register struct cmd *p;
296
297		for (p = cmds; p->c_name; p++)
298			if (strcmp(*argv, p->c_name) == 0)
299				break;
300		if (p->c_name == 0 && setaddr)
301			p++;	/* got src, do dst */
302		if (p->c_func) {
303			if (p->c_parameter == NEXTARG) {
304				if (argv[1] == NULL)
305					errx(1, "'%s' requires argument",
306					    p->c_name);
307				(*p->c_func)(argv[1]);
308				argc--, argv++;
309			} else
310				(*p->c_func)(*argv, p->c_parameter);
311		}
312		argc--, argv++;
313	}
314	if (af == AF_ISO)
315		adjust_nsellength();
316	if (setipdst && af==AF_NS) {
317		struct nsip_req rq;
318		int size = sizeof(rq);
319
320		rq.rq_ns = addreq.ifra_addr;
321		rq.rq_ip = addreq.ifra_dstaddr;
322
323		if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
324			Perror("Encapsulation Routing");
325	}
326	if (clearaddr) {
327		int ret;
328		strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name);
329		if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) {
330			if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
331				/* means no previous address for interface */
332			} else
333				Perror("ioctl (SIOCDIFADDR)");
334		}
335	}
336	if (newaddr) {
337		strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name);
338		if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0)
339			Perror("ioctl (SIOCAIFADDR)");
340	}
341	return(0);
342}
343#define RIDADDR 0
344#define ADDR	1
345#define MASK	2
346#define DSTADDR	3
347
348/*ARGSUSED*/
349setifaddr(addr, param)
350	char *addr;
351	short param;
352{
353	/*
354	 * Delay the ioctl to set the interface addr until flags are all set.
355	 * The address interpretation may depend on the flags,
356	 * and the flags may change when the address is set.
357	 */
358	setaddr++;
359	if (doalias == 0)
360		clearaddr = 1;
361	(*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
362}
363
364setifnetmask(addr)
365	char *addr;
366{
367	(*afp->af_getaddr)(addr, MASK);
368}
369
370setifbroadaddr(addr)
371	char *addr;
372{
373	(*afp->af_getaddr)(addr, DSTADDR);
374}
375
376setifipdst(addr)
377	char *addr;
378{
379	in_getaddr(addr, DSTADDR);
380	setipdst++;
381	clearaddr = 0;
382	newaddr = 0;
383}
384#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
385/*ARGSUSED*/
386notealias(addr, param)
387	char *addr;
388{
389	if (setaddr && doalias == 0 && param < 0)
390		bcopy((caddr_t)rqtosa(af_addreq),
391		      (caddr_t)rqtosa(af_ridreq),
392		      rqtosa(af_addreq)->sa_len);
393	doalias = param;
394	if (param < 0) {
395		clearaddr = 1;
396		newaddr = 0;
397	} else
398		clearaddr = 0;
399}
400
401/*ARGSUSED*/
402notrailers(vname, value)
403	char *vname;
404	int value;
405{
406	printf("Note: trailers are no longer sent, but always received\n");
407}
408
409/*ARGSUSED*/
410setifdstaddr(addr, param)
411	char *addr;
412	int param;
413{
414	(*afp->af_getaddr)(addr, DSTADDR);
415}
416
417setifflags(vname, value)
418	char *vname;
419	short value;
420{
421 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
422 		Perror("ioctl (SIOCGIFFLAGS)");
423 		exit(1);
424 	}
425	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
426 	flags = ifr.ifr_flags;
427
428	if (value < 0) {
429		value = -value;
430		flags &= ~value;
431	} else
432		flags |= value;
433	ifr.ifr_flags = flags;
434	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
435		Perror(vname);
436}
437
438setifmetric(val)
439	char *val;
440{
441	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
442	ifr.ifr_metric = atoi(val);
443	if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
444		perror("ioctl (set metric)");
445}
446
447setifmtu(val)
448	char *val;
449{
450	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
451	ifr.ifr_mtu = atoi(val);
452	if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
453		perror("ioctl (set mtu)");
454}
455
456setsnpaoffset(val)
457	char *val;
458{
459	iso_addreq.ifra_snpaoffset = atoi(val);
460}
461
462#define	IFFBITS \
463"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
464\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
465
466/*
467 * Print the status of the interface.  If an address family was
468 * specified, show it and it only; otherwise, show them all.
469 */
470status()
471{
472	register struct afswtch *p = afp;
473	short af = ifr.ifr_addr.sa_family;
474
475	printf("%s: ", name);
476	printb("flags", flags, IFFBITS);
477	if (metric)
478		printf(" metric %d", metric);
479	if (mtu)
480		printf(" mtu %d", mtu);
481	putchar('\n');
482	if ((p = afp) != NULL) {
483		(*p->af_status)(1);
484	} else for (p = afs; p->af_name; p++) {
485		ifr.ifr_addr.sa_family = p->af_af;
486		(*p->af_status)(0);
487	}
488}
489
490in_status(force)
491	int force;
492{
493	struct sockaddr_in *sin;
494	char *inet_ntoa();
495
496	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
497	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
498		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
499			if (!force)
500				return;
501			bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
502		} else
503			perror("ioctl (SIOCGIFADDR)");
504	}
505	sin = (struct sockaddr_in *)&ifr.ifr_addr;
506	printf("\tinet %s ", inet_ntoa(sin->sin_addr));
507	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
508	if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) {
509		if (errno != EADDRNOTAVAIL)
510			perror("ioctl (SIOCGIFNETMASK)");
511		bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
512	} else
513		netmask.sin_addr =
514		    ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
515	if (flags & IFF_POINTOPOINT) {
516		if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
517			if (errno == EADDRNOTAVAIL)
518			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
519			else
520			    perror("ioctl (SIOCGIFDSTADDR)");
521		}
522		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
523		sin = (struct sockaddr_in *)&ifr.ifr_dstaddr;
524		printf("--> %s ", inet_ntoa(sin->sin_addr));
525	}
526	printf("netmask 0x%x ", ntohl(netmask.sin_addr.s_addr));
527	if (flags & IFF_BROADCAST) {
528		if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifr) < 0) {
529			if (errno == EADDRNOTAVAIL)
530			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
531			else
532			    perror("ioctl (SIOCGIFADDR)");
533		}
534		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
535		sin = (struct sockaddr_in *)&ifr.ifr_addr;
536		if (sin->sin_addr.s_addr != 0)
537			printf("broadcast %s", inet_ntoa(sin->sin_addr));
538	}
539	putchar('\n');
540}
541
542
543xns_status(force)
544	int force;
545{
546	struct sockaddr_ns *sns;
547
548	close(s);
549	s = socket(AF_NS, SOCK_DGRAM, 0);
550	if (s < 0) {
551		if (errno == EPROTONOSUPPORT)
552			return;
553		perror("ifconfig: socket");
554		exit(1);
555	}
556	if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) < 0) {
557		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
558			if (!force)
559				return;
560			bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
561		} else
562			perror("ioctl (SIOCGIFADDR)");
563	}
564	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
565	sns = (struct sockaddr_ns *)&ifr.ifr_addr;
566	printf("\tns %s ", ns_ntoa(sns->sns_addr));
567	if (flags & IFF_POINTOPOINT) { /* by W. Nesheim@Cornell */
568		if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifr) < 0) {
569			if (errno == EADDRNOTAVAIL)
570			    bzero((char *)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
571			else
572			    Perror("ioctl (SIOCGIFDSTADDR)");
573		}
574		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
575		sns = (struct sockaddr_ns *)&ifr.ifr_dstaddr;
576		printf("--> %s ", ns_ntoa(sns->sns_addr));
577	}
578	putchar('\n');
579}
580
581iso_status(force)
582	int force;
583{
584	struct sockaddr_iso *siso;
585	struct iso_ifreq ifr;
586
587	close(s);
588	s = socket(AF_ISO, SOCK_DGRAM, 0);
589	if (s < 0) {
590		if (errno == EPROTONOSUPPORT)
591			return;
592		perror("ifconfig: socket");
593		exit(1);
594	}
595	bzero((caddr_t)&ifr, sizeof(ifr));
596	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
597	if (ioctl(s, SIOCGIFADDR_ISO, (caddr_t)&ifr) < 0) {
598		if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) {
599			if (!force)
600				return;
601			bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr));
602		} else {
603			perror("ioctl (SIOCGIFADDR_ISO)");
604			exit(1);
605		}
606	}
607	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
608	siso = &ifr.ifr_Addr;
609	printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
610	if (ioctl(s, SIOCGIFNETMASK_ISO, (caddr_t)&ifr) < 0) {
611		if (errno != EADDRNOTAVAIL)
612			perror("ioctl (SIOCGIFNETMASK_ISO)");
613	} else {
614		printf(" netmask %s ", iso_ntoa(&siso->siso_addr));
615	}
616	if (flags & IFF_POINTOPOINT) {
617		if (ioctl(s, SIOCGIFDSTADDR_ISO, (caddr_t)&ifr) < 0) {
618			if (errno == EADDRNOTAVAIL)
619			    bzero((char *)&ifr.ifr_Addr, sizeof(ifr.ifr_Addr));
620			else
621			    Perror("ioctl (SIOCGIFDSTADDR_ISO)");
622		}
623		strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
624		siso = &ifr.ifr_Addr;
625		printf("--> %s ", iso_ntoa(&siso->siso_addr));
626	}
627	putchar('\n');
628}
629
630kread(addr, buf, size)
631        u_long addr;
632        char *buf;
633        int size;
634{
635
636        if (kvm_read(kvmd, addr, buf, size) != size)
637                return (-1);
638        return (0);
639}
640
641/* Unashamedly stolen from netstat -- maybe someday we can us sysctl() */
642ether_status()
643{
644	struct nlist nl[] = { { "_ifnet" } , "" };
645	u_long addr, addr2;
646	struct ifnet ifnet;
647	union {
648		struct ifaddr ifa;
649		struct in_ifaddr in;
650		struct ns_ifaddr ns;
651		struct iso_ifaddr iso;
652	} ifaddr;
653	char *cp;
654	struct sockaddr *sa;
655	struct sockaddr_dl *sdl;
656	int n,m;
657	char ifacename[IFNAMSIZ];
658
659	/*
660	 * If we fail here it probably means we don't have permission to
661	 * read /dev/kmem. Best to just silently bail out. If we have
662	 * an error *after* we succeed in opening /dev/kmem, then we
663	 * should report it.
664	 */
665	if ((kvmd = kvm_open(NULL,NULL,NULL,O_RDONLY,NULL)) == NULL)
666		return;
667	if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) {
668		perror("ifconfig: kvm_nlist()");
669		return;
670	}
671	if (kread(nl[0].n_value, (char *)&addr, sizeof(addr))) {
672		perror("_ifnet");
673		return;
674	}
675	addr2 = 0;
676	while (addr || addr2) {
677		if (addr2 == 0) {
678                        if (kread(addr, (char *)&ifnet, sizeof ifnet) ||
679                           kread((u_long)ifnet.if_name, ifacename, IFNAMSIZ)){
680					perror("ifconfig: kvm_read()");
681					return;
682			}
683			addr = (u_long)ifnet.if_next;
684			addr2 = (u_long)ifnet.if_addrlist;
685		}
686		if (kread(addr2, (char *)&ifaddr, sizeof ifaddr)) {
687			addr2 = 0;
688                        continue;
689                }
690		sprintf(ifacename,"%s%d",ifacename, ifnet.if_unit);
691		if (!strncmp(name, ifacename, strlen(name))) {
692#define CP(x) ((char *)(x))
693			cp = (CP(ifaddr.ifa.ifa_addr) - CP(addr2)) +
694				CP(&ifaddr); sa = (struct sockaddr *)cp;
695			if (sa->sa_family == AF_LINK) {
696				sdl = (struct sockaddr_dl *)sa;
697				cp = (char *)LLADDR(sdl);
698				if ((n = sdl->sdl_alen) > 0) {
699					printf ("\tether ");
700                               		while (--n >= 0)
701						m += printf("%02x%c",
702							*cp++ & 0xff,
703							n > 0 ? ':' : ' ');
704					putchar('\n');
705				}
706				break;
707			}
708		}
709		addr2 = (u_long)ifaddr.ifa.ifa_next;
710	}
711	kvm_close(kvmd);
712}
713
714Perror(cmd)
715	char *cmd;
716{
717	extern int errno;
718
719	switch (errno) {
720
721	case ENXIO:
722		errx(1, "%s: no such interface", cmd);
723		break;
724
725	case EPERM:
726		errx(1, "%s: permission denied", cmd);
727		break;
728
729	default:
730		err(1, "%s", cmd);
731	}
732}
733
734struct	in_addr inet_makeaddr();
735
736#define SIN(x) ((struct sockaddr_in *) &(x))
737struct sockaddr_in *sintab[] = {
738SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
739SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
740
741in_getaddr(s, which)
742	char *s;
743{
744	register struct sockaddr_in *sin = sintab[which];
745	struct hostent *hp;
746	struct netent *np;
747	int val;
748
749	sin->sin_len = sizeof(*sin);
750	if (which != MASK)
751		sin->sin_family = AF_INET;
752
753	if (inet_aton(s, &sin->sin_addr))
754		;
755	else if (hp = gethostbyname(s))
756		bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
757	else if (np = getnetbyname(s))
758		sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
759	else
760		errx(1, "%s: bad value", s);
761}
762
763/*
764 * Print a value a la the %b format of the kernel's printf
765 */
766printb(s, v, bits)
767	char *s;
768	register char *bits;
769	register unsigned short v;
770{
771	register int i, any = 0;
772	register char c;
773
774	if (bits && *bits == 8)
775		printf("%s=%o", s, v);
776	else
777		printf("%s=%x", s, v);
778	bits++;
779	if (bits) {
780		putchar('<');
781		while (i = *bits++) {
782			if (v & (1 << (i-1))) {
783				if (any)
784					putchar(',');
785				any = 1;
786				for (; (c = *bits) > 32; bits++)
787					putchar(c);
788			} else
789				for (; *bits > 32; bits++)
790					;
791		}
792		putchar('>');
793	}
794}
795
796#define SNS(x) ((struct sockaddr_ns *) &(x))
797struct sockaddr_ns *snstab[] = {
798SNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
799SNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
800
801xns_getaddr(addr, which)
802char *addr;
803{
804	struct sockaddr_ns *sns = snstab[which];
805	struct ns_addr ns_addr();
806
807	sns->sns_family = AF_NS;
808	sns->sns_len = sizeof(*sns);
809	sns->sns_addr = ns_addr(addr);
810	if (which == MASK)
811		printf("Attempt to set XNS netmask will be ineffectual\n");
812}
813
814#define SISO(x) ((struct sockaddr_iso *) &(x))
815struct sockaddr_iso *sisotab[] = {
816SISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr),
817SISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
818
819iso_getaddr(addr, which)
820char *addr;
821{
822	register struct sockaddr_iso *siso = sisotab[which];
823	struct iso_addr *iso_addr();
824	siso->siso_addr = *iso_addr(addr);
825
826	if (which == MASK) {
827		siso->siso_len = TSEL(siso) - (caddr_t)(siso);
828		siso->siso_nlen = 0;
829	} else {
830		siso->siso_len = sizeof(*siso);
831		siso->siso_family = AF_ISO;
832	}
833}
834
835setnsellength(val)
836	char *val;
837{
838	nsellength = atoi(val);
839	if (nsellength < 0)
840		errx(1, "Negative NSEL length is absurd");
841	if (afp == 0 || afp->af_af != AF_ISO)
842		errx(1, "Setting NSEL length valid only for iso");
843}
844
845fixnsel(s)
846register struct sockaddr_iso *s;
847{
848	if (s->siso_family == 0)
849		return;
850	s->siso_tlen = nsellength;
851}
852
853adjust_nsellength()
854{
855	fixnsel(sisotab[RIDADDR]);
856	fixnsel(sisotab[ADDR]);
857	fixnsel(sisotab[DSTADDR]);
858}
859