1138593Ssam/*
2138593Ssam * Copyright (c) 1983, 1993
3138593Ssam *	The Regents of the University of California.  All rights reserved.
4138593Ssam *
5138593Ssam * Redistribution and use in source and binary forms, with or without
6138593Ssam * modification, are permitted provided that the following conditions
7138593Ssam * are met:
8138593Ssam * 1. Redistributions of source code must retain the above copyright
9138593Ssam *    notice, this list of conditions and the following disclaimer.
10138593Ssam * 2. Redistributions in binary form must reproduce the above copyright
11138593Ssam *    notice, this list of conditions and the following disclaimer in the
12138593Ssam *    documentation and/or other materials provided with the distribution.
13138593Ssam * 4. Neither the name of the University nor the names of its contributors
14138593Ssam *    may be used to endorse or promote products derived from this software
15138593Ssam *    without specific prior written permission.
16138593Ssam *
17138593Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18138593Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19138593Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20138593Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21138593Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22138593Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23138593Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24138593Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25138593Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26138593Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27138593Ssam * SUCH DAMAGE.
28138593Ssam */
29138593Ssam
30138593Ssam#ifndef lint
31138593Ssamstatic const char rcsid[] =
32138593Ssam  "$FreeBSD$";
33138593Ssam#endif /* not lint */
34138593Ssam
35138593Ssam#include <sys/types.h>
36138593Ssam#include <sys/ioctl.h>
37138593Ssam#include <sys/socket.h>
38138593Ssam#include <net/if.h>
39138593Ssam
40138593Ssam#include <netatalk/at.h>
41138593Ssam
42138593Ssam#include <err.h>
43138593Ssam#include <stdio.h>
44138593Ssam#include <stdlib.h>
45138593Ssam#include <string.h>
46138593Ssam#include <unistd.h>
47166956Ssam#include <ifaddrs.h>
48138593Ssam
49138593Ssam#include <arpa/inet.h>
50138593Ssam
51138593Ssam#include "ifconfig.h"
52138593Ssam
53138593Ssamstatic struct netrange at_nr;		/* AppleTalk net range */
54138593Ssamstatic struct ifaliasreq at_addreq;
55138593Ssam
56138593Ssam/* XXX  FIXME -- should use strtoul for better parsing. */
57138593Ssamstatic void
58138593Ssamsetatrange(const char *range, int dummy __unused, int s,
59138593Ssam    const struct afswtch *afp)
60138593Ssam{
61138593Ssam	u_int	first = 123, last = 123;
62138593Ssam
63138593Ssam	if (sscanf(range, "%u-%u", &first, &last) != 2
64138593Ssam	    || first == 0 || first > 0xffff
65138593Ssam	    || last == 0 || last > 0xffff || first > last)
66138593Ssam		errx(1, "%s: illegal net range: %u-%u", range, first, last);
67138593Ssam	at_nr.nr_firstnet = htons(first);
68138593Ssam	at_nr.nr_lastnet = htons(last);
69138593Ssam}
70138593Ssam
71138593Ssamstatic void
72138593Ssamsetatphase(const char *phase, int dummy __unused, int s,
73138593Ssam    const struct afswtch *afp)
74138593Ssam{
75138593Ssam	if (!strcmp(phase, "1"))
76138593Ssam		at_nr.nr_phase = 1;
77138593Ssam	else if (!strcmp(phase, "2"))
78138593Ssam		at_nr.nr_phase = 2;
79138593Ssam	else
80138593Ssam		errx(1, "%s: illegal phase", phase);
81138593Ssam}
82138593Ssam
83138593Ssamstatic void
84166956Ssamat_status(int s __unused, const struct ifaddrs *ifa)
85138593Ssam{
86138593Ssam	struct sockaddr_at *sat, null_sat;
87138593Ssam	struct netrange *nr;
88138593Ssam
89138593Ssam	memset(&null_sat, 0, sizeof(null_sat));
90138593Ssam
91166956Ssam	sat = (struct sockaddr_at *)ifa->ifa_addr;
92138593Ssam	if (sat == NULL)
93138593Ssam		return;
94138593Ssam	nr = &sat->sat_range.r_netrange;
95138593Ssam	printf("\tatalk %d.%d range %d-%d phase %d",
96138593Ssam		ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
97138593Ssam		ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
98166956Ssam	if (ifa->ifa_flags & IFF_POINTOPOINT) {
99166956Ssam		sat = (struct sockaddr_at *)ifa->ifa_dstaddr;
100166956Ssam		if (sat == NULL)
101138593Ssam			sat = &null_sat;
102138593Ssam		printf("--> %d.%d",
103138593Ssam			ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
104138593Ssam	}
105166956Ssam	if (ifa->ifa_flags & IFF_BROADCAST) {
106166956Ssam		sat = (struct sockaddr_at *)ifa->ifa_broadaddr;
107166956Ssam		if (sat != NULL)
108138593Ssam			printf(" broadcast %d.%d",
109138593Ssam				ntohs(sat->sat_addr.s_net),
110138593Ssam				sat->sat_addr.s_node);
111138593Ssam	}
112138593Ssam
113138593Ssam	putchar('\n');
114138593Ssam}
115138593Ssam
116138593Ssamstatic void
117138593Ssamat_getaddr(const char *addr, int which)
118138593Ssam{
119138593Ssam	struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr;
120138593Ssam	u_int net, node;
121138593Ssam
122138593Ssam	sat->sat_family = AF_APPLETALK;
123138593Ssam	sat->sat_len = sizeof(*sat);
124138593Ssam	if (which == MASK)
125138593Ssam		errx(1, "AppleTalk does not use netmasks");
126138593Ssam	if (sscanf(addr, "%u.%u", &net, &node) != 2
127138593Ssam	    || net > 0xffff || node > 0xfe)
128138593Ssam		errx(1, "%s: illegal address", addr);
129138593Ssam	sat->sat_addr.s_net = htons(net);
130138593Ssam	sat->sat_addr.s_node = node;
131138593Ssam}
132138593Ssam
133138593Ssamstatic void
134138593Ssamat_postproc(int s, const struct afswtch *afp)
135138593Ssam{
136138593Ssam	struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr;
137138593Ssam
138138593Ssam	if (at_nr.nr_phase == 0)
139138593Ssam		at_nr.nr_phase = 2;	/* Default phase 2 */
140138593Ssam	if (at_nr.nr_firstnet == 0)
141138593Ssam		at_nr.nr_firstnet =	/* Default range of one */
142138593Ssam		at_nr.nr_lastnet = sat->sat_addr.s_net;
143138593Ssam	printf("\tatalk %d.%d range %d-%d phase %d\n",
144138593Ssam		ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
145138593Ssam		ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet),
146138593Ssam		at_nr.nr_phase);
147138593Ssam	if ((u_short) ntohs(at_nr.nr_firstnet) >
148138593Ssam			(u_short) ntohs(sat->sat_addr.s_net)
149138593Ssam		    || (u_short) ntohs(at_nr.nr_lastnet) <
150138593Ssam			(u_short) ntohs(sat->sat_addr.s_net))
151138593Ssam		errx(1, "AppleTalk address is not in range");
152138593Ssam	sat->sat_range.r_netrange = at_nr;
153138593Ssam}
154138593Ssam
155138593Ssamstatic struct cmd atalk_cmds[] = {
156138593Ssam	DEF_CMD_ARG("range",	setatrange),
157138593Ssam	DEF_CMD_ARG("phase",	setatphase),
158138593Ssam};
159138593Ssam
160138593Ssamstatic struct afswtch af_atalk = {
161138593Ssam	.af_name	= "atalk",
162138593Ssam	.af_af		= AF_APPLETALK,
163138593Ssam	.af_status	= at_status,
164138593Ssam	.af_getaddr	= at_getaddr,
165138593Ssam	.af_postproc	= at_postproc,
166138593Ssam	.af_difaddr	= SIOCDIFADDR,
167138593Ssam	.af_aifaddr	= SIOCAIFADDR,
168138593Ssam	.af_ridreq	= &at_addreq,
169138593Ssam	.af_addreq	= &at_addreq,
170138593Ssam};
171138593Ssam
172138593Ssamstatic __constructor void
173138593Ssamatalk_ctor(void)
174138593Ssam{
175138593Ssam#define	N(a)	(sizeof(a) / sizeof(a[0]))
176194799Sdelphij	size_t i;
177138593Ssam
178138593Ssam	for (i = 0; i < N(atalk_cmds);  i++)
179138593Ssam		cmd_register(&atalk_cmds[i]);
180138593Ssam	af_register(&af_atalk);
181138593Ssam#undef N
182138593Ssam}
183