1/* $NetBSD: af_iso.c,v 1.13 2008/07/15 21:27:58 dyoung Exp $ */ 2 3/* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#ifndef lint 34__RCSID("$NetBSD: af_iso.c,v 1.13 2008/07/15 21:27:58 dyoung Exp $"); 35#endif /* not lint */ 36 37#include <err.h> 38#include <errno.h> 39#include <string.h> 40#include <stddef.h> 41#include <stdlib.h> 42#include <stdio.h> 43#include <util.h> 44 45#include <sys/param.h> 46#include <sys/ioctl.h> 47#include <sys/socket.h> 48 49#include <net/if.h> 50 51#define EON 52#include <netiso/iso.h> 53#include <netiso/iso_var.h> 54 55#include "env.h" 56#include "parse.h" 57#include "extern.h" 58#include "af_inetany.h" 59#include "prog_ops.h" 60 61#define DEFNSELLEN 1 62 63static void iso_constructor(void) __attribute__((constructor)); 64static int setnsellength(prop_dictionary_t, prop_dictionary_t); 65static void iso_status(prop_dictionary_t, prop_dictionary_t, bool); 66static void iso_commit_address(prop_dictionary_t, prop_dictionary_t); 67 68static struct afswtch isoaf = { 69 .af_name = "iso", .af_af = AF_ISO, .af_status = iso_status, 70 .af_addr_commit = iso_commit_address 71}; 72 73struct pinteger parse_snpaoffset = PINTEGER_INITIALIZER1(&snpaoffset, 74 "snpaoffset", INT_MIN, INT_MAX, 10, NULL, "snpaoffset", 75 &command_root.pb_parser); 76struct pinteger parse_nsellength = PINTEGER_INITIALIZER1(&nsellength, 77 "nsellength", 0, UINT8_MAX, 10, setnsellength, "nsellength", 78 &command_root.pb_parser); 79 80static const struct kwinst isokw[] = { 81 {.k_word = "nsellength", .k_nextparser = &parse_nsellength.pi_parser} 82 , {.k_word = "snpaoffset", .k_nextparser = &parse_snpaoffset.pi_parser} 83}; 84 85struct pkw iso = PKW_INITIALIZER(&iso, "ISO", NULL, NULL, 86 isokw, __arraycount(isokw), NULL); 87 88static cmdloop_branch_t branch; 89 90static void 91fixnsel(struct sockaddr_iso *siso, uint8_t nsellength) 92{ 93 siso->siso_tlen = nsellength; 94} 95 96/* fixup mask */ 97static int 98iso_pre_aifaddr(prop_dictionary_t env, const struct afparam *param) 99{ 100 struct sockaddr_iso *siso; 101 102 siso = param->mask.buf; 103 siso->siso_len = TSEL(siso) - (char *)(siso); 104 siso->siso_nlen = 0; 105 return 0; 106} 107 108static void 109iso_commit_address(prop_dictionary_t env, prop_dictionary_t oenv) 110{ 111 uint8_t nsellength; 112 struct iso_ifreq ifr = {.ifr_Addr = {.siso_tlen = DEFNSELLEN}}; 113 struct iso_aliasreq ifra = { 114 .ifra_dstaddr = {.siso_tlen = DEFNSELLEN}, 115 .ifra_addr = {.siso_tlen = DEFNSELLEN} 116 }; 117 struct afparam isoparam = { 118 .req = BUFPARAM(ifra) 119 , .dgreq = BUFPARAM(ifr) 120 , .name = { 121 {.buf = ifr.ifr_name, 122 .buflen = sizeof(ifr.ifr_name)} 123 , {.buf = ifra.ifra_name, 124 .buflen = sizeof(ifra.ifra_name)} 125 } 126 , .dgaddr = BUFPARAM(ifr.ifr_Addr) 127 , .addr = BUFPARAM(ifra.ifra_addr) 128 , .dst = BUFPARAM(ifra.ifra_dstaddr) 129 , .brd = BUFPARAM(ifra.ifra_broadaddr) 130 , .mask = BUFPARAM(ifra.ifra_mask) 131 , .aifaddr = IFADDR_PARAM(SIOCAIFADDR_ISO) 132 , .difaddr = IFADDR_PARAM(SIOCDIFADDR_ISO) 133 , .gifaddr = IFADDR_PARAM(SIOCGIFADDR_ISO) 134 , .defmask = {.buf = NULL, .buflen = 0} 135 , .pre_aifaddr = iso_pre_aifaddr 136 }; 137 int64_t snpaoffset; 138 139 if (prop_dictionary_get_int64(env, "snpaoffset", &snpaoffset)) 140 ifra.ifra_snpaoffset = snpaoffset; 141 142 if (prop_dictionary_get_uint8(env, "nsellength", &nsellength)) { 143 fixnsel(&ifr.ifr_Addr, nsellength); 144 fixnsel(&ifra.ifra_addr, nsellength); 145 fixnsel(&ifra.ifra_dstaddr, nsellength); 146 } 147 commit_address(env, oenv, &isoparam); 148} 149 150static int 151setnsellength(prop_dictionary_t env, prop_dictionary_t oenv) 152{ 153 int af; 154 155 if ((af = getaf(env)) == -1 || af != AF_ISO) 156 errx(EXIT_FAILURE, "Setting NSEL length valid only for ISO"); 157 158 return 0; 159 160} 161 162static void 163iso_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force) 164{ 165 struct sockaddr_iso *siso; 166 struct iso_ifreq isoifr; 167 int s; 168 const char *ifname; 169 unsigned short flags; 170 171 if ((ifname = getifinfo(env, oenv, &flags)) == NULL) 172 err(EXIT_FAILURE, "%s: getifinfo", __func__); 173 174 if ((s = getsock(AF_ISO)) == -1) { 175 if (errno == EAFNOSUPPORT) 176 return; 177 err(EXIT_FAILURE, "socket"); 178 } 179 memset(&isoifr, 0, sizeof(isoifr)); 180 estrlcpy(isoifr.ifr_name, ifname, sizeof(isoifr.ifr_name)); 181 if (prog_ioctl(s, SIOCGIFADDR_ISO, &isoifr) == -1) { 182 if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT) { 183 if (!force) 184 return; 185 memset(&isoifr.ifr_Addr, 0, sizeof(isoifr.ifr_Addr)); 186 } else 187 warn("SIOCGIFADDR_ISO"); 188 } 189 strlcpy(isoifr.ifr_name, ifname, sizeof(isoifr.ifr_name)); 190 siso = &isoifr.ifr_Addr; 191 printf("\tiso %s", iso_ntoa(&siso->siso_addr)); 192 if (prog_ioctl(s, SIOCGIFNETMASK_ISO, &isoifr) == -1) { 193 if (errno == EADDRNOTAVAIL) 194 memset(&isoifr.ifr_Addr, 0, sizeof(isoifr.ifr_Addr)); 195 else 196 warn("SIOCGIFNETMASK_ISO"); 197 } else { 198 if (siso->siso_len > offsetof(struct sockaddr_iso, siso_addr)) 199 siso->siso_addr.isoa_len = siso->siso_len 200 - offsetof(struct sockaddr_iso, siso_addr); 201 printf(" netmask %s", iso_ntoa(&siso->siso_addr)); 202 } 203 204 if (flags & IFF_POINTOPOINT) { 205 if (prog_ioctl(s, SIOCGIFDSTADDR_ISO, &isoifr) == -1) { 206 if (errno == EADDRNOTAVAIL) 207 memset(&isoifr.ifr_Addr, 0, 208 sizeof(isoifr.ifr_Addr)); 209 else 210 warn("SIOCGIFDSTADDR_ISO"); 211 } 212 strlcpy(isoifr.ifr_name, ifname, sizeof(isoifr.ifr_name)); 213 siso = &isoifr.ifr_Addr; 214 printf(" --> %s", iso_ntoa(&siso->siso_addr)); 215 } 216 printf("\n"); 217} 218 219static void 220iso_constructor(void) 221{ 222 register_family(&isoaf); 223 cmdloop_branch_init(&branch, &iso.pk_parser); 224 register_cmdloop_branch(&branch); 225} 226