af_atalk.c revision 138593
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: head/sbin/ifconfig/af_atalk.c 138593 2004-12-08 19:18:07Z sam $";
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#include <net/route.h>		/* for RTX_IFA */
40138593Ssam
41138593Ssam#include <netatalk/at.h>
42138593Ssam
43138593Ssam#include <err.h>
44138593Ssam#include <stdio.h>
45138593Ssam#include <stdlib.h>
46138593Ssam#include <string.h>
47138593Ssam#include <unistd.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
84138593Ssamat_status(int s __unused, const struct rt_addrinfo * info)
85138593Ssam{
86138593Ssam	struct sockaddr_at *sat, null_sat;
87138593Ssam	struct netrange *nr;
88138593Ssam
89138593Ssam	memset(&null_sat, 0, sizeof(null_sat));
90138593Ssam
91138593Ssam	sat = (struct sockaddr_at *)info->rti_info[RTAX_IFA];
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);
98138593Ssam	if (flags & IFF_POINTOPOINT) {
99138593Ssam		/* note RTAX_BRD overlap with IFF_BROADCAST */
100138593Ssam		sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD];
101138593Ssam		if (!sat)
102138593Ssam			sat = &null_sat;
103138593Ssam		printf("--> %d.%d",
104138593Ssam			ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
105138593Ssam	}
106138593Ssam	if (flags & IFF_BROADCAST) {
107138593Ssam		/* note RTAX_BRD overlap with IFF_POINTOPOINT */
108138593Ssam		sat = (struct sockaddr_at *)info->rti_info[RTAX_BRD];
109138593Ssam		if (sat)
110138593Ssam			printf(" broadcast %d.%d",
111138593Ssam				ntohs(sat->sat_addr.s_net),
112138593Ssam				sat->sat_addr.s_node);
113138593Ssam	}
114138593Ssam
115138593Ssam	putchar('\n');
116138593Ssam}
117138593Ssam
118138593Ssamstatic void
119138593Ssamat_getaddr(const char *addr, int which)
120138593Ssam{
121138593Ssam	struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr;
122138593Ssam	u_int net, node;
123138593Ssam
124138593Ssam	sat->sat_family = AF_APPLETALK;
125138593Ssam	sat->sat_len = sizeof(*sat);
126138593Ssam	if (which == MASK)
127138593Ssam		errx(1, "AppleTalk does not use netmasks");
128138593Ssam	if (sscanf(addr, "%u.%u", &net, &node) != 2
129138593Ssam	    || net > 0xffff || node > 0xfe)
130138593Ssam		errx(1, "%s: illegal address", addr);
131138593Ssam	sat->sat_addr.s_net = htons(net);
132138593Ssam	sat->sat_addr.s_node = node;
133138593Ssam}
134138593Ssam
135138593Ssamstatic void
136138593Ssamat_postproc(int s, const struct afswtch *afp)
137138593Ssam{
138138593Ssam	struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr;
139138593Ssam
140138593Ssam	if (at_nr.nr_phase == 0)
141138593Ssam		at_nr.nr_phase = 2;	/* Default phase 2 */
142138593Ssam	if (at_nr.nr_firstnet == 0)
143138593Ssam		at_nr.nr_firstnet =	/* Default range of one */
144138593Ssam		at_nr.nr_lastnet = sat->sat_addr.s_net;
145138593Ssam	printf("\tatalk %d.%d range %d-%d phase %d\n",
146138593Ssam		ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
147138593Ssam		ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet),
148138593Ssam		at_nr.nr_phase);
149138593Ssam	if ((u_short) ntohs(at_nr.nr_firstnet) >
150138593Ssam			(u_short) ntohs(sat->sat_addr.s_net)
151138593Ssam		    || (u_short) ntohs(at_nr.nr_lastnet) <
152138593Ssam			(u_short) ntohs(sat->sat_addr.s_net))
153138593Ssam		errx(1, "AppleTalk address is not in range");
154138593Ssam	sat->sat_range.r_netrange = at_nr;
155138593Ssam}
156138593Ssam
157138593Ssamstatic struct cmd atalk_cmds[] = {
158138593Ssam	DEF_CMD_ARG("range",	setatrange),
159138593Ssam	DEF_CMD_ARG("phase",	setatphase),
160138593Ssam};
161138593Ssam
162138593Ssamstatic struct afswtch af_atalk = {
163138593Ssam	.af_name	= "atalk",
164138593Ssam	.af_af		= AF_APPLETALK,
165138593Ssam	.af_status	= at_status,
166138593Ssam	.af_getaddr	= at_getaddr,
167138593Ssam	.af_postproc	= at_postproc,
168138593Ssam	.af_difaddr	= SIOCDIFADDR,
169138593Ssam	.af_aifaddr	= SIOCAIFADDR,
170138593Ssam	.af_ridreq	= &at_addreq,
171138593Ssam	.af_addreq	= &at_addreq,
172138593Ssam};
173138593Ssam
174138593Ssamstatic __constructor void
175138593Ssamatalk_ctor(void)
176138593Ssam{
177138593Ssam#define	N(a)	(sizeof(a) / sizeof(a[0]))
178138593Ssam	int i;
179138593Ssam
180138593Ssam	for (i = 0; i < N(atalk_cmds);  i++)
181138593Ssam		cmd_register(&atalk_cmds[i]);
182138593Ssam	af_register(&af_atalk);
183138593Ssam#undef N
184138593Ssam}
185