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