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