ifconfig.c revision 25448
1219089Spjd/*
2219089Spjd * Copyright (c) 1983, 1993
3219089Spjd *	The Regents of the University of California.  All rights reserved.
4219089Spjd *
5219089Spjd * Redistribution and use in source and binary forms, with or without
6219089Spjd * modification, are permitted provided that the following conditions
7219089Spjd * are met:
8219089Spjd * 1. Redistributions of source code must retain the above copyright
9219089Spjd *    notice, this list of conditions and the following disclaimer.
10219089Spjd * 2. Redistributions in binary form must reproduce the above copyright
11219089Spjd *    notice, this list of conditions and the following disclaimer in the
12219089Spjd *    documentation and/or other materials provided with the distribution.
13219089Spjd * 3. All advertising materials mentioning features or use of this software
14219089Spjd *    must display the following acknowledgement:
15219089Spjd *	This product includes software developed by the University of
16219089Spjd *	California, Berkeley and its contributors.
17219089Spjd * 4. Neither the name of the University nor the names of its contributors
18219089Spjd *    may be used to endorse or promote products derived from this software
19219089Spjd *    without specific prior written permission.
20219089Spjd *
21219089Spjd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22219089Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23249195Smm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24219089Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25219089Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26219089Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27219089Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28219089Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29219089Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30219089Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31219089Spjd * SUCH DAMAGE.
32219089Spjd */
33219089Spjd
34219089Spjd#ifndef lint
35219089Spjdstatic const char copyright[] =
36219089Spjd"@(#) Copyright (c) 1983, 1993\n\
37219089Spjd	The Regents of the University of California.  All rights reserved.\n";
38219089Spjd#endif /* not lint */
39219089Spjd
40219089Spjd#ifndef lint
41219089Spjd/*
42219089Spjdstatic char sccsid[] = "@(#)ifconfig.c	8.2 (Berkeley) 2/16/94";
43219089Spjd*/
44219089Spjdstatic const char rcsid[] =
45219089Spjd	"$Id: ifconfig.c,v 1.24 1997/02/22 14:32:33 peter Exp $";
46219089Spjd#endif /* not lint */
47219089Spjd
48236884Smm#include <sys/param.h>
49219089Spjd#include <sys/ioctl.h>
50219089Spjd#include <sys/socket.h>
51219089Spjd#include <sys/sysctl.h>
52219089Spjd#include <sys/time.h>
53219089Spjd
54219089Spjd#include <net/if.h>
55219089Spjd#include <net/if_var.h>
56248571Smm#include <net/if_dl.h>
57219089Spjd#include <net/if_types.h>
58219089Spjd#include <net/route.h>
59237972Smm
60237972Smm/* IP */
61237972Smm#include <netinet/in.h>
62237972Smm#include <netinet/in_var.h>
63219089Spjd#include <arpa/inet.h>
64237972Smm#include <netdb.h>
65237972Smm
66237972Smm/* IPX */
67237972Smm#define	IPXIP
68219089Spjd#define IPTUNNEL
69268650Sdelphij#include <netipx/ipx.h>
70237972Smm#include <netipx/ipx_if.h>
71237972Smm
72237972Smm/* Appletalk */
73237972Smm#include <netatalk/at.h>
74237972Smm
75237972Smm/* XNS */
76237972Smm#ifdef NS
77237972Smm#define	NSIP
78237972Smm#include <netns/ns.h>
79237972Smm#include <netns/ns_if.h>
80237972Smm#endif
81237972Smm
82237972Smm/* OSI */
83237972Smm#ifdef ISO
84237972Smm#define EON
85237972Smm#include <netiso/iso.h>
86237972Smm#include <netiso/iso_var.h>
87237972Smm#endif
88237972Smm
89237972Smm#include <ctype.h>
90237972Smm#include <err.h>
91237972Smm#include <errno.h>
92237972Smm#include <fcntl.h>
93237972Smm#include <stdio.h>
94237972Smm#include <stdlib.h>
95237972Smm#include <string.h>
96237972Smm#include <unistd.h>
97237972Smm
98237972Smmstruct	ifreq		ifr, ridreq;
99237972Smmstruct	ifaliasreq	addreq;
100219089Spjd#ifdef ISO
101219089Spjdstruct	iso_ifreq	iso_ridreq;
102219089Spjdstruct	iso_aliasreq	iso_addreq;
103219089Spjd#endif
104219089Spjdstruct	sockaddr_in	netmask;
105219089Spjdstruct	netrange	at_nr;		/* AppleTalk net range */
106219089Spjd
107219089Spjdchar	name[32];
108219089Spjdint	flags;
109219089Spjdint	metric;
110219089Spjdint	mtu;
111219089Spjd#ifdef ISO
112219089Spjdint	nsellength = 1;
113219089Spjd#endif
114219089Spjdint	setaddr;
115219089Spjdint	setipdst;
116219089Spjdint	doalias;
117219089Spjdint	clearaddr;
118219089Spjdint	newaddr = 1;
119219089Spjdint	s;
120219089Spjd
121219089Spjdstruct	afswtch;
122219089Spjd
123219089Spjdvoid	Perror __P((const char *cmd));
124219089Spjdvoid	checkatrange __P((struct sockaddr_at *));
125219089Spjdint	ifconfig __P((int argc, char *const *argv, int af,
126249858Smm		      const struct afswtch *rafp));
127249858Smmvoid	notealias __P((const char *, int));
128249858Smmvoid	printb __P((const char *s, unsigned value, const char *bits));
129249858Smmvoid	rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
130249858Smmvoid	status __P((void));
131249858Smm
132249858Smmtypedef	void c_func __P((const char *cmd, int arg));
133263390Sdelphijc_func	setatphase, setatrange;
134249858Smmc_func	setifaddr, setifbroadaddr, setifdstaddr, setifnetmask;
135219089Spjdc_func	setifipdst;
136219089Spjdc_func	setifflags, setifmetric, setifmtu;
137219089Spjd
138219089Spjd#ifdef ISO
139219089Spjdc_func	setsnpaoffset, setnsellength;
140219089Spjd#endif
141219089Spjd
142219089Spjd#define	NEXTARG		0xffffff
143219089Spjd
144219089Spjdconst
145219089Spjdstruct	cmd {
146219089Spjd	const	char *c_name;
147219089Spjd	int	c_parameter;		/* NEXTARG means next argv */
148219089Spjd	void	(*c_func) __P((const char *, int));
149219089Spjd} cmds[] = {
150219089Spjd	{ "up",		IFF_UP,		setifflags } ,
151219089Spjd	{ "down",	-IFF_UP,	setifflags },
152219089Spjd	{ "arp",	-IFF_NOARP,	setifflags },
153219089Spjd	{ "-arp",	IFF_NOARP,	setifflags },
154219089Spjd	{ "debug",	IFF_DEBUG,	setifflags },
155219089Spjd	{ "-debug",	-IFF_DEBUG,	setifflags },
156219089Spjd	{ "alias",	IFF_UP,		notealias },
157219089Spjd	{ "-alias",	-IFF_UP,	notealias },
158219089Spjd	{ "delete",	-IFF_UP,	notealias },
159219089Spjd#ifdef notdef
160219089Spjd#define	EN_SWABIPS	0x1000
161219089Spjd	{ "swabips",	EN_SWABIPS,	setifflags },
162219089Spjd	{ "-swabips",	-EN_SWABIPS,	setifflags },
163219089Spjd#endif
164219089Spjd	{ "netmask",	NEXTARG,	setifnetmask },
165219089Spjd	{ "range",	NEXTARG,	setatrange },
166219089Spjd	{ "phase",	NEXTARG,	setatphase },
167219089Spjd	{ "metric",	NEXTARG,	setifmetric },
168219089Spjd	{ "broadcast",	NEXTARG,	setifbroadaddr },
169219089Spjd	{ "ipdst",	NEXTARG,	setifipdst },
170219089Spjd#ifdef ISO
171219089Spjd	{ "snpaoffset",	NEXTARG,	setsnpaoffset },
172219089Spjd	{ "nsellength",	NEXTARG,	setnsellength },
173219089Spjd#endif
174219089Spjd	{ "link0",	IFF_LINK0,	setifflags },
175219089Spjd	{ "-link0",	-IFF_LINK0,	setifflags },
176219089Spjd	{ "link1",	IFF_LINK1,	setifflags },
177219089Spjd	{ "-link1",	-IFF_LINK1,	setifflags },
178219089Spjd	{ "link2",	IFF_LINK2,	setifflags },
179219089Spjd	{ "-link2",	-IFF_LINK2,	setifflags },
180219089Spjd	{ "normal",	-IFF_LINK0,	setifflags },
181219089Spjd	{ "compress",	IFF_LINK0,	setifflags },
182219089Spjd	{ "noicmp",	IFF_LINK1,	setifflags },
183219089Spjd	{ "mtu",	NEXTARG,	setifmtu },
184219089Spjd	{ 0,		0,		setifaddr },
185219089Spjd	{ 0,		0,		setifdstaddr },
186219089Spjd};
187219089Spjd
188219089Spjd/*
189219089Spjd * XNS support liberally adapted from code written at the University of
190219089Spjd * Maryland principally by James O'Toole and Chris Torek.
191219089Spjd */
192219089Spjdtypedef	void af_status __P((int));
193219089Spjdtypedef	void af_getaddr __P((const char *, int));
194248571Smm
195219089Spjdaf_status	in_status, ipx_status, at_status, ether_status;
196248571Smmaf_getaddr	in_getaddr, ipx_getaddr, at_getaddr;
197219089Spjd
198219089Spjd#ifdef NS
199249195Smmaf_status	xns_status;
200219089Spjdaf_getaddr	xns_getaddr;
201219089Spjd#endif
202219089Spjd#ifdef ISO
203219089Spjdaf_status	iso_status;
204219089Spjdaf_getaddr	iso_getaddr;
205248571Smm#endif
206219089Spjd
207248571Smm/* Known address families */
208248571Smmconst
209219089Spjdstruct	afswtch {
210219089Spjd	const char *af_name;
211219089Spjd	short af_af;
212219089Spjd	af_status *af_status;
213219089Spjd	af_getaddr *af_getaddr;
214219089Spjd	int af_difaddr;
215219089Spjd	int af_aifaddr;
216219089Spjd	caddr_t af_ridreq;
217219089Spjd	caddr_t af_addreq;
218219089Spjd} afs[] = {
219219089Spjd#define C(x) ((caddr_t) &x)
220219089Spjd	{ "inet", AF_INET, in_status, in_getaddr,
221219089Spjd	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
222219089Spjd	{ "ipx", AF_IPX, ipx_status, ipx_getaddr,
223219089Spjd	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
224219089Spjd	{ "atalk", AF_APPLETALK, at_status, at_getaddr,
225254112Sdelphij	     SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) },
226219089Spjd#ifdef NS
227219089Spjd	{ "ns", AF_NS, xns_status, xns_getaddr,
228219089Spjd	     SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
229219089Spjd#endif
230219089Spjd#ifdef ISO
231219089Spjd	{ "iso", AF_ISO, iso_status, iso_getaddr,
232219089Spjd	     SIOCDIFADDR_ISO, SIOCAIFADDR_ISO, C(iso_ridreq), C(iso_addreq) },
233219089Spjd#endif
234219089Spjd	{ "ether", AF_INET, ether_status, NULL },	/* XXX not real!! */
235219089Spjd	{ 0,	0,	    0,		0 }
236219089Spjd};
237219089Spjd
238219089Spjdconst struct afswtch *afp;	/*the address family being set or asked about*/
239219089Spjd
240219089Spjd/*
241219089Spjd * Expand the compacted form of addresses as returned via the
242219089Spjd * configuration read via sysctl().
243219089Spjd */
244219089Spjd
245219089Spjd#define ROUNDUP(a) \
246219089Spjd	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
247219089Spjd#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
248219089Spjd
249219089Spjdvoid
250219089Spjdrt_xaddrs(cp, cplim, rtinfo)
251219089Spjd	caddr_t cp, cplim;
252219089Spjd	struct rt_addrinfo *rtinfo;
253219089Spjd{
254219089Spjd	struct sockaddr *sa;
255219089Spjd	int i;
256219089Spjd
257219089Spjd	memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
258219089Spjd	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
259219089Spjd		if ((rtinfo->rti_addrs & (1 << i)) == 0)
260219089Spjd			continue;
261219089Spjd		rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
262219089Spjd		ADVANCE(cp, sa);
263219089Spjd	}
264219089Spjd}
265219089Spjd
266219089Spjd
267219089Spjd/*
268248571Smm * Grunge for new-style sysctl() decoding.. :-(
269219089Spjd * Apologies to the world for committing gross things like this in 1996..
270219089Spjd */
271219089Spjdstruct if_msghdr *ifm;
272219089Spjdstruct ifa_msghdr *ifam;
273219089Spjdstruct sockaddr_dl *sdl;
274219089Spjdstruct rt_addrinfo info;
275219089Spjdchar *buf, *lim, *next;
276219089Spjd
277219089Spjdint
278219089Spjdmain(argc, argv)
279219089Spjd	int argc;
280219089Spjd	char *const *argv;
281219089Spjd{
282219089Spjd	int af = AF_INET;
283219089Spjd	const struct afswtch *rafp;
284219089Spjd
285219089Spjd	size_t needed;
286219089Spjd	int mib[6];
287219089Spjd	int all;
288219089Spjd
289219089Spjd	rafp = 0;
290219089Spjd
291219089Spjd	if (argc < 2) {
292219089Spjd		fprintf(stderr, "usage: ifconfig interface\n%s%s%s%s%s%s%s",
293219089Spjd		    "\t[ af [ address [ dest_addr ] ] [ up ] [ down ]",
294219089Spjd			    "[ netmask mask ] ]\n",
295219089Spjd		    "\t[ metric n ]\n",
296219089Spjd		    "\t[ mtu n ]\n",
297219089Spjd		    "\t[ arp | -arp ]\n",
298219089Spjd		    "\t[ link0 | -link0 ] [ link1 | -link1 ] [ link2 | -link2 ] \n",
299219089Spjd		    "\t[ -a ] [ -ad ] [ -au ]\n");
300219089Spjd		exit(1);
301219089Spjd	}
302219089Spjd	argc--, argv++;
303219089Spjd	strncpy(name, *argv, sizeof(name));
304219089Spjd	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
305219089Spjd	argc--, argv++;
306219089Spjd	if (argc > 0) {
307219089Spjd		for (afp = rafp = afs; rafp->af_name; rafp++)
308219089Spjd			if (strcmp(rafp->af_name, *argv) == 0) {
309219089Spjd				afp = rafp; argc--; argv++;
310219089Spjd				break;
311219089Spjd			}
312219089Spjd		rafp = afp;
313219089Spjd		af = ifr.ifr_addr.sa_family = rafp->af_af;
314219089Spjd	}
315219089Spjd
316219089Spjd	mib[0] = CTL_NET;
317248571Smm	mib[1] = PF_ROUTE;
318219089Spjd	mib[2] = 0;
319219089Spjd	mib[3] = 0;	/* address family */
320219089Spjd	mib[4] = NET_RT_IFLIST;
321219089Spjd	mib[5] = 0;
322219089Spjd
323219089Spjd	/* if particular family specified, only ask about it */
324219089Spjd	if (afp) {
325219089Spjd		mib[3] = afp->af_af;
326219089Spjd	}
327219089Spjd
328219089Spjd	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
329219089Spjd		errx(1, "iflist-sysctl-estimate");
330219089Spjd	if ((buf = malloc(needed)) == NULL)
331219089Spjd		errx(1, "malloc");
332219089Spjd	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
333219089Spjd		errx(1, "actual retrieval of interface table");
334219089Spjd	lim = buf + needed;
335219089Spjd
336219089Spjd	all = 0;
337219089Spjd	if (strcmp(name, "-a") == 0)
338219089Spjd		all = 1;	/* All interfaces */
339219089Spjd	else if (strcmp(name, "-au") == 0)
340219089Spjd		all = 2;	/* All IFF_UPinterfaces */
341219089Spjd	else if (strcmp(name, "-ad") == 0)
342219089Spjd		all = 3;	/* All !IFF_UP interfaces */
343219089Spjd
344219089Spjd	for (next = buf; next < lim; next += ifm->ifm_msglen) {
345219089Spjd
346219089Spjd		ifm = (struct if_msghdr *)next;
347219089Spjd
348219089Spjd		/* XXX: Swallow up leftover NEWADDR messages */
349219089Spjd		if (ifm->ifm_type == RTM_NEWADDR)
350219089Spjd			continue;
351219089Spjd
352219089Spjd		if (ifm->ifm_type == RTM_IFINFO) {
353219089Spjd			sdl = (struct sockaddr_dl *)(ifm + 1);
354219089Spjd			flags = ifm->ifm_flags;
355248571Smm		} else {
356219089Spjd			errx(1, "out of sync parsing NET_RT_IFLIST");
357248571Smm		}
358219089Spjd
359219089Spjd		switch(all) {
360249195Smm		case -1:
361219089Spjd		case 0:
362219089Spjd			if (strlen(name) != sdl->sdl_nlen)
363219089Spjd				continue; /* not same len */
364219089Spjd			if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
365219089Spjd				continue; /* not same name */
366248571Smm			break;
367219089Spjd		case 1:
368248571Smm			break;	/* always do it */
369219089Spjd		case 2:
370219089Spjd			if ((flags & IFF_UP) == 0)
371219089Spjd				continue; /* not up */
372219089Spjd			break;
373219089Spjd		case 3:
374219089Spjd			if (flags & IFF_UP)
375219089Spjd				continue; /* not down */
376219089Spjd			break;
377248571Smm		}
378248571Smm
379219089Spjd		if (all > 0) {
380219089Spjd			strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
381219089Spjd			name[sdl->sdl_nlen] = '\0';
382219089Spjd		}
383219089Spjd
384219089Spjd		if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
385219089Spjd			perror("ifconfig: socket");
386219089Spjd			exit(1);
387219089Spjd		}
388219089Spjd
389219089Spjd		ifconfig(argc, argv, af, rafp);
390219089Spjd
391219089Spjd		close(s);
392219089Spjd
393219089Spjd		if (all == 0) {
394219089Spjd			all = -1; /* flag it as 'done' */
395219089Spjd			break;
396219089Spjd		}
397219089Spjd	}
398219089Spjd	free(buf);
399240868Spjd
400240868Spjd	if (all == 0)
401219089Spjd		errx(1, "interface %s does not exist", name);
402219089Spjd
403219089Spjd
404219089Spjd	exit (0);
405219089Spjd}
406219089Spjd
407219089Spjd
408219089Spjd
409219089Spjdint
410219089Spjdifconfig(argc,argv,af,rafp)
411219089Spjd	int argc;
412219089Spjd	char *const *argv;
413219089Spjd	int af;
414219089Spjd	const struct afswtch *rafp;
415248571Smm{
416219089Spjd
417219089Spjd	strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
418219089Spjd
419219089Spjd	if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
420219089Spjd		perror("ioctl (SIOCGIFMETRIC)");
421219089Spjd	else
422219089Spjd		metric = ifr.ifr_metric;
423219089Spjd
424219089Spjd	if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
425237972Smm		perror("ioctl (SIOCGIFMTU)");
426219089Spjd	else
427219089Spjd		mtu = ifr.ifr_mtu;
428219089Spjd
429219089Spjd	if (argc == 0) {
430219089Spjd		status();
431219089Spjd		return(0);
432219089Spjd	}
433219089Spjd
434236884Smm	while (argc > 0) {
435219089Spjd		register const struct cmd *p;
436219089Spjd
437219089Spjd		for (p = cmds; p->c_name; p++)
438219089Spjd			if (strcmp(*argv, p->c_name) == 0)
439219089Spjd				break;
440219089Spjd		if (p->c_name == 0 && setaddr)
441219089Spjd			p++;	/* got src, do dst */
442219089Spjd		if (p->c_func) {
443219089Spjd			if (p->c_parameter == NEXTARG) {
444219089Spjd				if (argv[1] == NULL)
445255437Sdelphij					errx(1, "'%s' requires argument",
446219089Spjd					    p->c_name);
447219089Spjd				(*p->c_func)(argv[1], 0);
448219089Spjd				argc--, argv++;
449219089Spjd			} else
450219089Spjd				(*p->c_func)(*argv, p->c_parameter);
451219089Spjd		}
452219089Spjd		argc--, argv++;
453219089Spjd	}
454219089Spjd#ifdef ISO
455219089Spjd	if (af == AF_ISO)
456219089Spjd		adjust_nsellength();
457219089Spjd#endif
458219089Spjd	if (setipdst && af==AF_IPX) {
459219089Spjd		struct ipxip_req rq;
460219089Spjd		int size = sizeof(rq);
461219089Spjd
462219089Spjd		rq.rq_ipx = addreq.ifra_addr;
463219089Spjd		rq.rq_ip = addreq.ifra_dstaddr;
464219089Spjd
465219089Spjd		if (setsockopt(s, 0, SO_IPXIP_ROUTE, &rq, size) < 0)
466219089Spjd			Perror("Encapsulation Routing");
467219089Spjd	}
468219089Spjd	if (af == AF_APPLETALK)
469219089Spjd		checkatrange((struct sockaddr_at *) &addreq.ifra_addr);
470219089Spjd#ifdef NS
471219089Spjd	if (setipdst && af==AF_NS) {
472219089Spjd		struct nsip_req rq;
473219089Spjd		int size = sizeof(rq);
474219089Spjd
475219089Spjd		rq.rq_ns = addreq.ifra_addr;
476219089Spjd		rq.rq_ip = addreq.ifra_dstaddr;
477219089Spjd
478219089Spjd		if (setsockopt(s, 0, SO_NSIP_ROUTE, &rq, size) < 0)
479219089Spjd			Perror("Encapsulation Routing");
480219089Spjd	}
481219089Spjd#endif
482263397Sdelphij	if (clearaddr) {
483219089Spjd		if (rafp->af_ridreq == NULL || rafp->af_difaddr == 0) {
484219089Spjd			warnx("interface %s cannot change %s addresses!",
485219089Spjd			      name, rafp->af_name);
486219089Spjd			clearaddr = NULL;
487219089Spjd		}
488219089Spjd	}
489219089Spjd	if (clearaddr) {
490219089Spjd		int ret;
491219089Spjd		strncpy(rafp->af_ridreq, name, sizeof ifr.ifr_name);
492219089Spjd		if ((ret = ioctl(s, rafp->af_difaddr, rafp->af_ridreq)) < 0) {
493219089Spjd			if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
494219089Spjd				/* means no previous address for interface */
495219089Spjd			} else
496219089Spjd				Perror("ioctl (SIOCDIFADDR)");
497219089Spjd		}
498219089Spjd	}
499219089Spjd	if (newaddr) {
500219089Spjd		if (rafp->af_ridreq == NULL || rafp->af_difaddr == 0) {
501219089Spjd			warnx("interface %s cannot change %s addresses!",
502219089Spjd			      name, rafp->af_name);
503219089Spjd			newaddr = NULL;
504219089Spjd		}
505219089Spjd	}
506219089Spjd	if (newaddr) {
507219089Spjd		strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name);
508219089Spjd		if (ioctl(s, rafp->af_aifaddr, rafp->af_addreq) < 0)
509219089Spjd			Perror("ioctl (SIOCAIFADDR)");
510219089Spjd	}
511219089Spjd	return(0);
512219089Spjd}
513219089Spjd#define RIDADDR 0
514263397Sdelphij#define ADDR	1
515263397Sdelphij#define MASK	2
516219089Spjd#define DSTADDR	3
517219089Spjd
518219089Spjd/*ARGSUSED*/
519219089Spjdvoid
520219089Spjdsetifaddr(addr, param)
521219089Spjd	const char *addr;
522219089Spjd	int param;
523219089Spjd{
524219089Spjd	/*
525219089Spjd	 * Delay the ioctl to set the interface addr until flags are all set.
526219089Spjd	 * The address interpretation may depend on the flags,
527219089Spjd	 * and the flags may change when the address is set.
528219089Spjd	 */
529219089Spjd	setaddr++;
530219089Spjd	if (doalias == 0)
531219089Spjd		clearaddr = 1;
532219089Spjd	(*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR));
533219089Spjd}
534219089Spjd
535219089Spjdvoid
536219089Spjdsetifnetmask(addr, dummy)
537219089Spjd	const char *addr;
538219089Spjd	int dummy __unused;
539219089Spjd{
540219089Spjd	(*afp->af_getaddr)(addr, MASK);
541219089Spjd}
542219089Spjd
543219089Spjdvoid
544219089Spjdsetifbroadaddr(addr, dummy)
545219089Spjd	const char *addr;
546219089Spjd	int dummy __unused;
547219089Spjd{
548219089Spjd	(*afp->af_getaddr)(addr, DSTADDR);
549219089Spjd}
550219089Spjd
551219089Spjdvoid
552219089Spjdsetifipdst(addr, dummy)
553219089Spjd	const char *addr;
554219089Spjd	int dummy __unused;
555219089Spjd{
556219089Spjd	in_getaddr(addr, DSTADDR);
557219089Spjd	setipdst++;
558219089Spjd	clearaddr = 0;
559219089Spjd	newaddr = 0;
560219089Spjd}
561219089Spjd#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
562219089Spjd
563219089Spjdvoid
564219089Spjdnotealias(addr, param)
565219089Spjd	const char *addr;
566219089Spjd	int param;
567219089Spjd{
568219089Spjd	if (setaddr && doalias == 0 && param < 0)
569219089Spjd		bcopy((caddr_t)rqtosa(af_addreq),
570219089Spjd		      (caddr_t)rqtosa(af_ridreq),
571219089Spjd		      rqtosa(af_addreq)->sa_len);
572219089Spjd	doalias = param;
573219089Spjd	if (param < 0) {
574219089Spjd		clearaddr = 1;
575246666Smm		newaddr = 0;
576219089Spjd	} else
577219089Spjd		clearaddr = 0;
578219089Spjd}
579219089Spjd
580219089Spjd/*ARGSUSED*/
581219089Spjdvoid
582219089Spjdsetifdstaddr(addr, param)
583219089Spjd	const char *addr;
584219089Spjd	int param __unused;
585219089Spjd{
586236884Smm	(*afp->af_getaddr)(addr, DSTADDR);
587219089Spjd}
588219089Spjd
589219089Spjdvoid
590219089Spjdsetifflags(vname, value)
591219089Spjd	const char *vname;
592236884Smm	int value;
593219089Spjd{
594219089Spjd 	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
595219089Spjd 		Perror("ioctl (SIOCGIFFLAGS)");
596219089Spjd 		exit(1);
597219089Spjd 	}
598219089Spjd	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
599219089Spjd 	flags = ifr.ifr_flags;
600219089Spjd
601219089Spjd	if (value < 0) {
602219089Spjd		value = -value;
603219089Spjd		flags &= ~value;
604219089Spjd	} else
605219089Spjd		flags |= value;
606219089Spjd	ifr.ifr_flags = flags;
607219089Spjd	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
608219089Spjd		Perror(vname);
609219089Spjd}
610219089Spjd
611219089Spjdvoid
612219089Spjdsetifmetric(val, dummy)
613219089Spjd	const char *val;
614219089Spjd	int dummy __unused;
615219089Spjd{
616219089Spjd	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
617219089Spjd	ifr.ifr_metric = atoi(val);
618219089Spjd	if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
619219089Spjd		perror("ioctl (set metric)");
620219089Spjd}
621219089Spjd
622219089Spjdvoid
623219089Spjdsetifmtu(val, dummy)
624219089Spjd	const char *val;
625219089Spjd	int dummy __unused;
626219089Spjd{
627219089Spjd	strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
628219089Spjd	ifr.ifr_mtu = atoi(val);
629219089Spjd	if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
630219089Spjd		perror("ioctl (set mtu)");
631219089Spjd}
632219089Spjd
633246666Smm#ifdef ISO
634219089Spjdvoid
635219089Spjdsetsnpaoffset(val, dummy)
636219089Spjd	char *val;
637219089Spjd	int dummy __unused;
638219089Spjd{
639219089Spjd	iso_addreq.ifra_snpaoffset = atoi(val);
640219089Spjd}
641219089Spjd#endif
642219089Spjd
643219089Spjd#define	IFFBITS \
644219089Spjd"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6b6\7RUNNING" \
645219089Spjd"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
646219089Spjd"\20MULTICAST"
647219089Spjd
648219089Spjd/*
649219089Spjd * Print the status of the interface.  If an address family was
650219089Spjd * specified, show it and it only; otherwise, show them all.
651219089Spjd */
652219089Spjdvoid
653219089Spjdstatus()
654219089Spjd{
655246666Smm	const struct afswtch *p = NULL;
656219089Spjd	char *mynext;
657219089Spjd	struct if_msghdr *myifm;
658219089Spjd
659219089Spjd	printf("%s: ", name);
660219089Spjd	printb("flags", flags, IFFBITS);
661219089Spjd	if (metric)
662219089Spjd		printf(" metric %d", metric);
663219089Spjd	if (mtu)
664219089Spjd		printf(" mtu %d", mtu);
665219089Spjd	putchar('\n');
666219089Spjd
667246666Smm	/*
668219089Spjd	 * XXX: Sigh. This is bad, I know.  At this point, we may have
669219089Spjd	 * *zero* RTM_NEWADDR's, so we have to "feel the water" before
670219089Spjd	 * incrementing the loop.  One day, I might feel inspired enough
671219089Spjd	 * to get the top level loop to pass a count down here so we
672219089Spjd	 * dont have to mess with this.  -Peter
673219089Spjd	 */
674219089Spjd	myifm = ifm;
675219089Spjd
676219089Spjd	while (1) {
677219089Spjd
678219089Spjd		mynext = next + ifm->ifm_msglen;
679219089Spjd
680219089Spjd		if (mynext >= lim)
681219089Spjd			break;
682219089Spjd
683219089Spjd		myifm = (struct if_msghdr *)mynext;
684219089Spjd
685219089Spjd		if (myifm->ifm_type != RTM_NEWADDR)
686219089Spjd			break;
687219089Spjd
688219089Spjd		next = mynext;
689246666Smm
690219089Spjd		ifm = (struct if_msghdr *)next;
691219089Spjd
692219089Spjd		ifam = (struct ifa_msghdr *)myifm;
693219089Spjd		info.rti_addrs = ifam->ifam_addrs;
694219089Spjd
695219089Spjd		/* Expand the compacted addresses */
696219089Spjd		rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
697219089Spjd			  &info);
698219089Spjd
699219089Spjd		if (afp) {
700219089Spjd			if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family &&
701219089Spjd			    afp->af_status != ether_status) {
702219089Spjd				p = afp;
703219089Spjd				if (p->af_status != ether_status)
704219089Spjd					(*p->af_status)(1);
705219089Spjd			}
706219089Spjd		} else for (p = afs; p->af_name; p++) {
707219089Spjd			if (p->af_af == info.rti_info[RTAX_IFA]->sa_family &&
708219089Spjd			    p->af_status != ether_status)
709219089Spjd				(*p->af_status)(0);
710219089Spjd		}
711219089Spjd	}
712219089Spjd	if (afp == NULL || afp->af_status == ether_status)
713219089Spjd		ether_status(0);
714219089Spjd	else if (afp && !p) {
715219089Spjd		warnx("%s has no %s IFA address!", name, afp->af_name);
716219089Spjd	}
717219089Spjd}
718219089Spjd
719219089Spjdvoid
720219089Spjdin_status(force)
721219089Spjd	int force;
722219089Spjd{
723219089Spjd	struct sockaddr_in *sin, null_sin;
724219089Spjd
725219089Spjd	memset(&null_sin, 0, sizeof(null_sin));
726219089Spjd
727219089Spjd	sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA];
728219089Spjd	if (!sin || sin->sin_family != AF_INET) {
729219089Spjd		if (!force)
730219089Spjd			return;
731219089Spjd		/* warnx("%s has no AF_INET IFA address!", name); */
732219089Spjd		sin = &null_sin;
733219089Spjd	}
734219089Spjd	printf("\tinet %s ", inet_ntoa(sin->sin_addr));
735219089Spjd
736219089Spjd	if (flags & IFF_POINTOPOINT) {
737219089Spjd		/* note RTAX_BRD overlap with IFF_BROADCAST */
738219089Spjd		sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD];
739219089Spjd		if (!sin)
740219089Spjd			sin = &null_sin;
741219089Spjd		printf("--> %s ", inet_ntoa(sin->sin_addr));
742219089Spjd	}
743219089Spjd
744219089Spjd	sin = (struct sockaddr_in *)info.rti_info[RTAX_NETMASK];
745219089Spjd	if (!sin)
746219089Spjd		sin = &null_sin;
747219089Spjd	printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
748219089Spjd
749219089Spjd	if (flags & IFF_BROADCAST) {
750219089Spjd		/* note RTAX_BRD overlap with IFF_POINTOPOINT */
751219089Spjd		sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD];
752219089Spjd		if (sin && sin->sin_addr.s_addr != 0)
753219089Spjd			printf("broadcast %s", inet_ntoa(sin->sin_addr));
754219089Spjd	}
755219089Spjd	putchar('\n');
756219089Spjd}
757219089Spjd
758219089Spjdvoid
759219089Spjdipx_status(force)
760219089Spjd	int force;
761219089Spjd{
762219089Spjd	struct sockaddr_ipx *sipx, null_sipx;
763219089Spjd
764219089Spjd	close(s);
765219089Spjd	s = socket(AF_IPX, SOCK_DGRAM, 0);
766219089Spjd	if (s < 0) {
767263397Sdelphij		if (errno == EPROTONOSUPPORT)
768219089Spjd			return;
769219089Spjd		perror("ifconfig: socket");
770219089Spjd		exit(1);
771219089Spjd	}
772219089Spjd
773219089Spjd	memset(&null_sipx, 0, sizeof(null_sipx));
774219089Spjd
775219089Spjd	sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_IFA];
776219089Spjd	if (!sipx || sipx->sipx_family != AF_IPX) {
777219089Spjd		if (!force)
778219089Spjd			return;
779219089Spjd		warnx("%s has no AF_IPX IFA address!", name);
780219089Spjd		sipx = &null_sipx;
781219089Spjd	}
782219089Spjd	printf("\tipx %s ", ipx_ntoa(sipx->sipx_addr));
783219089Spjd
784219089Spjd	if (flags & IFF_POINTOPOINT) {
785219089Spjd		sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_BRD];
786219089Spjd		if (!sipx)
787219089Spjd			sipx = &null_sipx;
788219089Spjd		printf("--> %s ", ipx_ntoa(sipx->sipx_addr));
789219089Spjd	}
790219089Spjd	putchar('\n');
791219089Spjd
792219089Spjd}
793219089Spjd
794219089Spjdvoid
795219089Spjdat_status(force)
796219089Spjd	int force;
797219089Spjd{
798219089Spjd	struct sockaddr_at *sat, null_sat;
799219089Spjd	struct netrange *nr;
800219089Spjd
801219089Spjd	memset(&null_sat, 0, sizeof(null_sat));
802219089Spjd
803254112Sdelphij	sat = (struct sockaddr_at *)info.rti_info[RTAX_IFA];
804219089Spjd	if (!sat || sat->sat_family != AF_APPLETALK) {
805219089Spjd		if (!force)
806219089Spjd			return;
807219089Spjd		sat = &null_sat;
808219089Spjd	}
809219089Spjd	nr = &sat->sat_range.r_netrange;
810219089Spjd	printf("\tatalk %d.%d range %d-%d phase %d",
811219089Spjd		ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
812219089Spjd		ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
813219089Spjd	if (flags & IFF_POINTOPOINT) {
814219089Spjd		/* note RTAX_BRD overlap with IFF_BROADCAST */
815219089Spjd		sat = (struct sockaddr_at *)info.rti_info[RTAX_BRD];
816219089Spjd		if (!sat)
817219089Spjd			sat = &null_sat;
818219089Spjd		printf("--> %d.%d",
819219089Spjd			ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
820219089Spjd	}
821219089Spjd	if (flags & IFF_BROADCAST) {
822219089Spjd		/* note RTAX_BRD overlap with IFF_POINTOPOINT */
823219089Spjd		sat = (struct sockaddr_at *)info.rti_info[RTAX_BRD];
824219089Spjd		if (sat)
825219089Spjd			printf(" broadcast %d.%d",
826219089Spjd				ntohs(sat->sat_addr.s_net),
827219089Spjd				sat->sat_addr.s_node);
828219089Spjd	}
829219089Spjd
830219089Spjd	putchar('\n');
831219089Spjd}
832219089Spjd
833219089Spjd#ifdef NS
834219089Spjdvoid
835219089Spjdxns_status(force)
836219089Spjd	int force;
837219089Spjd{
838219089Spjd	struct sockaddr_ns *sns, null_sns;
839219089Spjd
840219089Spjd	close(s);
841219089Spjd	s = socket(AF_NS, SOCK_DGRAM, 0);
842219089Spjd	if (s < 0) {
843219089Spjd		if (errno == EPROTONOSUPPORT)
844219089Spjd			return;
845219089Spjd		perror("ifconfig: socket");
846219089Spjd		exit(1);
847219089Spjd	}
848219089Spjd	memset(&null_sns, 0, sizeof(null_sns));
849219089Spjd
850219089Spjd	sns = (struct sockaddr_ns *)info.rti_info[RTAX_IFA];
851219089Spjd	if (!sns || sns->sns_family != AF_NS) {
852219089Spjd		if (!force)
853219089Spjd			return;
854219089Spjd		/* warnx("%s has no AF_NS IFA address!", name); */
855219089Spjd		sns = &null_sns;
856219089Spjd	}
857219089Spjd	printf("\tns %s ", ns_ntoa(sns->sns_addr));
858219089Spjd
859219089Spjd	if (flags & IFF_POINTOPOINT) {
860219089Spjd		sns = (struct sockaddr_ns *)info.rti_info[RTAX_BRD];
861219089Spjd		if (!sns)
862219089Spjd			sns = &null_sns;
863219089Spjd		printf("--> %s ", ns_ntoa(sns->sns_addr));
864219089Spjd	}
865219089Spjd
866219089Spjd	putchar('\n');
867219089Spjd}
868219089Spjd#endif
869219089Spjd
870219089Spjd#ifdef ISO
871219089Spjdvoid
872219089Spjdiso_status(force)
873219089Spjd	int force;
874219089Spjd{
875219089Spjd	struct sockaddr_iso *siso, null_siso;
876219089Spjd
877219089Spjd	close(s);
878219089Spjd	s = socket(AF_ISO, SOCK_DGRAM, 0);
879219089Spjd	if (s < 0) {
880219089Spjd		if (errno == EPROTONOSUPPORT)
881219089Spjd			return;
882219089Spjd		perror("ifconfig: socket");
883219089Spjd		exit(1);
884219089Spjd	}
885219089Spjd
886219089Spjd	memset(&null_siso, 0, sizeof(null_siso));
887219089Spjd
888219089Spjd	siso = (struct sockaddr_iso *)info.rti_info[RTAX_IFA];
889219089Spjd	if (!siso || siso->siso_family != AF_ISO) {
890219089Spjd		if (!force)
891219089Spjd			return;
892219089Spjd		/* warnx("%s has no AF_ISO IFA address!", name); */
893219089Spjd		siso = &null_siso;
894219089Spjd	}
895219089Spjd	printf("\tiso %s ", iso_ntoa(&siso->siso_addr));
896219089Spjd
897219089Spjd	/* XXX: is this right? is the ISO netmask meant to be before P2P? */
898219089Spjd	siso = (struct sockaddr_iso *)info.rti_info[RTAX_NETMASK];
899219089Spjd	if (siso)
900219089Spjd		printf(" netmask %s ", iso_ntoa(&siso->siso_addr));
901219089Spjd
902219089Spjd	if (flags & IFF_POINTOPOINT) {
903219089Spjd		siso = (struct sockaddr_iso *)info.rti_info[RTAX_BRD];
904219089Spjd		if (!siso)
905219089Spjd			siso = &null_siso;
906219089Spjd		printf("--> %s ", iso_ntoa(&siso->siso_addr));
907219089Spjd	}
908219089Spjd
909219089Spjd	putchar('\n');
910219089Spjd}
911219089Spjd#endif
912219089Spjd
913219089Spjdvoid
914219089Spjdether_status(force)
915219089Spjd	int force __unused;
916219089Spjd{
917219089Spjd	char *cp;
918219089Spjd	int n;
919219089Spjd
920219089Spjd	cp = (char *)LLADDR(sdl);
921219089Spjd	if ((n = sdl->sdl_alen) > 0) {
922219089Spjd		if (sdl->sdl_type == IFT_ETHER)
923219089Spjd			printf ("\tether ");
924219089Spjd		else
925219089Spjd			printf ("\tlladdr ");
926219089Spjd             	while (--n >= 0)
927219089Spjd			printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' ');
928219089Spjd		putchar('\n');
929219089Spjd	}
930219089Spjd}
931219089Spjd
932219089Spjdvoid
933219089SpjdPerror(cmd)
934219089Spjd	const char *cmd;
935219089Spjd{
936219089Spjd	switch (errno) {
937219089Spjd
938219089Spjd	case ENXIO:
939219089Spjd		errx(1, "%s: no such interface", cmd);
940219089Spjd		break;
941219089Spjd
942219089Spjd	case EPERM:
943219089Spjd		errx(1, "%s: permission denied", cmd);
944219089Spjd		break;
945219089Spjd
946219089Spjd	default:
947219089Spjd		err(1, "%s", cmd);
948219089Spjd	}
949219089Spjd}
950219089Spjd
951219089Spjd#define SIN(x) ((struct sockaddr_in *) &(x))
952219089Spjdstruct sockaddr_in *sintab[] = {
953219089SpjdSIN(ridreq.ifr_addr), SIN(addreq.ifra_addr),
954219089SpjdSIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)};
955219089Spjd
956219089Spjdvoid
957219089Spjdin_getaddr(s, which)
958219089Spjd	const char *s;
959219089Spjd	int which;
960219089Spjd{
961219089Spjd	register struct sockaddr_in *sin = sintab[which];
962219089Spjd	struct hostent *hp;
963219089Spjd	struct netent *np;
964219089Spjd
965219089Spjd	sin->sin_len = sizeof(*sin);
966219089Spjd	if (which != MASK)
967219089Spjd		sin->sin_family = AF_INET;
968219089Spjd
969219089Spjd	if (inet_aton(s, &sin->sin_addr))
970219089Spjd		return;
971219089Spjd	if ((hp = gethostbyname(s)) != 0)
972219089Spjd		bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
973219089Spjd	else if ((np = getnetbyname(s)) != 0)
974219089Spjd		sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
975219089Spjd	else
976219089Spjd		errx(1, "%s: bad value", s);
977219089Spjd}
978219089Spjd
979219089Spjd/*
980219089Spjd * Print a value a la the %b format of the kernel's printf
981219089Spjd */
982219089Spjdvoid
983219089Spjdprintb(s, v, bits)
984219089Spjd	const char *s;
985219089Spjd	register unsigned v;
986219089Spjd	register const char *bits;
987219089Spjd{
988248571Smm	register int i, any = 0;
989219089Spjd	register char c;
990219089Spjd
991219089Spjd	if (bits && *bits == 8)
992219089Spjd		printf("%s=%o", s, v);
993219089Spjd	else
994219089Spjd		printf("%s=%x", s, v);
995248571Smm	bits++;
996248571Smm	if (bits) {
997248571Smm		putchar('<');
998248571Smm		while ((i = *bits++) != '\0') {
999219089Spjd			if (v & (1 << (i-1))) {
1000219089Spjd				if (any)
1001219089Spjd					putchar(',');
1002248571Smm				any = 1;
1003248571Smm				for (; (c = *bits) > 32; bits++)
1004248571Smm					putchar(c);
1005248571Smm			} else
1006219089Spjd				for (; *bits > 32; bits++)
1007248571Smm					;
1008248571Smm		}
1009248571Smm		putchar('>');
1010248571Smm	}
1011219089Spjd}
1012248571Smm
1013248571Smm#define SIPX(x) ((struct sockaddr_ipx *) &(x))
1014248571Smmstruct sockaddr_ipx *sipxtab[] = {
1015219089SpjdSIPX(ridreq.ifr_addr), SIPX(addreq.ifra_addr),
1016219089SpjdSIPX(addreq.ifra_mask), SIPX(addreq.ifra_broadaddr)};
1017219089Spjd
1018219089Spjdvoid
1019219089Spjdipx_getaddr(addr, which)
1020219089Spjd	const char *addr;
1021219089Spjd	int which;
1022219089Spjd{
1023219089Spjd	struct sockaddr_ipx *sipx = sipxtab[which];
1024219089Spjd
1025219089Spjd	sipx->sipx_family = AF_IPX;
1026219089Spjd	sipx->sipx_len = sizeof(*sipx);
1027219089Spjd	sipx->sipx_addr = ipx_addr(addr);
1028219089Spjd	if (which == MASK)
1029219089Spjd		printf("Attempt to set IPX netmask will be ineffectual\n");
1030219089Spjd}
1031219089Spjd
1032219089Spjdvoid
1033219089Spjdat_getaddr(addr, which)
1034219089Spjd	const char *addr;
1035219089Spjd	int which;
1036219089Spjd{
1037219089Spjd	struct sockaddr_at *sat = (struct sockaddr_at *) &addreq.ifra_addr;
1038219089Spjd	u_int net, node;
1039219089Spjd
1040219089Spjd	sat->sat_family = AF_APPLETALK;
1041219089Spjd	sat->sat_len = sizeof(*sat);
1042219089Spjd	if (which == MASK)
1043219089Spjd		errx(1, "AppleTalk does not use netmasks\n");
1044219089Spjd	if (sscanf(addr, "%u.%u", &net, &node) != 2
1045219089Spjd	    || net > 0xffff || node > 0xfe)
1046219089Spjd		errx(1, "%s: illegal address", addr);
1047219089Spjd	sat->sat_addr.s_net = htons(net);
1048219089Spjd	sat->sat_addr.s_node = node;
1049219089Spjd}
1050219089Spjd
1051219089Spjd/* XXX  FIXME -- should use strtoul for better parsing. */
1052219089Spjdvoid
1053219089Spjdsetatrange(range, dummy)
1054219089Spjd	const char *range;
1055219089Spjd	int dummy __unused;
1056219089Spjd{
1057219089Spjd	u_short	first = 123, last = 123;
1058219089Spjd
1059219089Spjd	if (sscanf(range, "%hu-%hu", &first, &last) != 2
1060219089Spjd	    || first == 0 || first > 0xffff
1061219089Spjd	    || last == 0 || last > 0xffff || first > last)
1062219089Spjd		errx(1, "%s: illegal net range: %u-%u", range, first, last);
1063219089Spjd	at_nr.nr_firstnet = htons(first);
1064219089Spjd	at_nr.nr_lastnet = htons(last);
1065219089Spjd}
1066219089Spjd
1067219089Spjdvoid
1068219089Spjdsetatphase(phase, dummy)
1069219089Spjd	const char *phase;
1070219089Spjd	int dummy __unused;
1071219089Spjd{
1072219089Spjd	if (!strcmp(phase, "1"))
1073219089Spjd		at_nr.nr_phase = 1;
1074219089Spjd	else if (!strcmp(phase, "2"))
1075219089Spjd		at_nr.nr_phase = 2;
1076219089Spjd	else
1077219089Spjd		errx(1, "%s: illegal phase", phase);
1078219089Spjd}
1079219089Spjd
1080219089Spjdvoid
1081219089Spjdcheckatrange(struct sockaddr_at *sat)
1082219089Spjd{
1083219089Spjd	if (at_nr.nr_phase == 0)
1084219089Spjd		at_nr.nr_phase = 2;	/* Default phase 2 */
1085219089Spjd	if (at_nr.nr_firstnet == 0)
1086219089Spjd		at_nr.nr_firstnet =	/* Default range of one */
1087219089Spjd		at_nr.nr_lastnet = sat->sat_addr.s_net;
1088219089Spjdprintf("\tatalk %d.%d range %d-%d phase %d\n",
1089219089Spjd	ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
1090219089Spjd	ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet), at_nr.nr_phase);
1091219089Spjd	if ((u_short) ntohs(at_nr.nr_firstnet) >
1092219089Spjd			(u_short) ntohs(sat->sat_addr.s_net)
1093219089Spjd		    || (u_short) ntohs(at_nr.nr_lastnet) <
1094219089Spjd			(u_short) ntohs(sat->sat_addr.s_net))
1095219089Spjd		errx(1, "AppleTalk address is not in range");
1096219089Spjd	sat->sat_range.r_netrange = at_nr;
1097219089Spjd}
1098219089Spjd
1099219089Spjd#ifdef NS
1100219089Spjd#define SNS(x) ((struct sockaddr_ns *) &(x))
1101219089Spjdstruct sockaddr_ns *snstab[] = {
1102219089SpjdSNS(ridreq.ifr_addr), SNS(addreq.ifra_addr),
1103248571SmmSNS(addreq.ifra_mask), SNS(addreq.ifra_broadaddr)};
1104219089Spjd
1105219089Spjdvoid
1106248571Smmxns_getaddr(addr, which)
1107219089Spjd	const char *addr;
1108219089Spjd	int which;
1109219089Spjd{
1110219089Spjd	struct sockaddr_ns *sns = snstab[which];
1111219089Spjd
1112248571Smm	sns->sns_family = AF_NS;
1113248571Smm	sns->sns_len = sizeof(*sns);
1114219089Spjd	sns->sns_addr = ns_addr(addr);
1115219089Spjd	if (which == MASK)
1116219089Spjd		printf("Attempt to set XNS netmask will be ineffectual\n");
1117219089Spjd}
1118219089Spjd#endif
1119219089Spjd
1120219089Spjd#ifdef ISO
1121219089Spjd#define SISO(x) ((struct sockaddr_iso *) &(x))
1122219089Spjdstruct sockaddr_iso *sisotab[] = {
1123248571SmmSISO(iso_ridreq.ifr_Addr), SISO(iso_addreq.ifra_addr),
1124219089SpjdSISO(iso_addreq.ifra_mask), SISO(iso_addreq.ifra_dstaddr)};
1125219089Spjd
1126219089Spjdvoid
1127219089Spjdiso_getaddr(addr, which)
1128219089Spjdchar *addr;
1129219089Spjd{
1130248571Smm	register struct sockaddr_iso *siso = sisotab[which];
1131219089Spjd	struct iso_addr *iso_addr();
1132219089Spjd	siso->siso_addr = *iso_addr(addr);
1133219089Spjd
1134219089Spjd	if (which == MASK) {
1135219089Spjd		siso->siso_len = TSEL(siso) - (caddr_t)(siso);
1136219089Spjd		siso->siso_nlen = 0;
1137219089Spjd	} else {
1138219089Spjd		siso->siso_len = sizeof(*siso);
1139219089Spjd		siso->siso_family = AF_ISO;
1140219089Spjd	}
1141219089Spjd}
1142219089Spjd
1143219089Spjdvoid
1144219089Spjdsetnsellength(val)
1145219089Spjd	char *val;
1146219089Spjd{
1147219089Spjd	nsellength = atoi(val);
1148219089Spjd	if (nsellength < 0)
1149219089Spjd		errx(1, "Negative NSEL length is absurd");
1150219089Spjd	if (afp == 0 || afp->af_af != AF_ISO)
1151219089Spjd		errx(1, "Setting NSEL length valid only for iso");
1152219089Spjd}
1153219089Spjd
1154219089Spjdvoid
1155219089Spjdfixnsel(s)
1156219089Spjdregister struct sockaddr_iso *s;
1157219089Spjd{
1158219089Spjd	if (s->siso_family == 0)
1159219089Spjd		return;
1160219089Spjd	s->siso_tlen = nsellength;
1161219089Spjd}
1162219089Spjd
1163219089Spjdvoid
1164219089Spjdadjust_nsellength()
1165219089Spjd{
1166219089Spjd	fixnsel(sisotab[RIDADDR]);
1167219089Spjd	fixnsel(sisotab[ADDR]);
1168219089Spjd	fixnsel(sisotab[DSTADDR]);
1169219089Spjd}
1170219089Spjd#endif
1171219089Spjd