1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This file contains a routine used to validate a ifconfig-style interface 31*7c478bd9Sstevel@tonic-gate * specification 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <ctype.h> 36*7c478bd9Sstevel@tonic-gate #include <alloca.h> 37*7c478bd9Sstevel@tonic-gate #include <errno.h> 38*7c478bd9Sstevel@tonic-gate #include <string.h> 39*7c478bd9Sstevel@tonic-gate #include <libinetutil.h> 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate * Given a token with a logical unit spec, return the logical unit converted 43*7c478bd9Sstevel@tonic-gate * to a uint_t. 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * Returns: 0 for success, nonzero if an error occurred. errno is set if 46*7c478bd9Sstevel@tonic-gate * necessary. 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate static int 49*7c478bd9Sstevel@tonic-gate getlun(const char *bp, int bpsize, uint_t *lun) 50*7c478bd9Sstevel@tonic-gate { 51*7c478bd9Sstevel@tonic-gate char *ep = (char *)&bp[bpsize - 1]; 52*7c478bd9Sstevel@tonic-gate char *sp = strchr(bp, ':'), *tp; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* A logical unit spec looks like: <token>:<unsigned int>\0 */ 55*7c478bd9Sstevel@tonic-gate if (isdigit(*bp) || !isdigit(*ep) || sp == NULL || 56*7c478bd9Sstevel@tonic-gate strchr(sp + 1, ':') != NULL) { 57*7c478bd9Sstevel@tonic-gate errno = EINVAL; 58*7c478bd9Sstevel@tonic-gate return (-1); 59*7c478bd9Sstevel@tonic-gate } 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate *sp++ = '\0'; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* Lun must be all digits */ 64*7c478bd9Sstevel@tonic-gate for (tp = sp; tp < ep && isdigit(*tp); tp++) 65*7c478bd9Sstevel@tonic-gate /* Null body */; 66*7c478bd9Sstevel@tonic-gate if (tp != ep) { 67*7c478bd9Sstevel@tonic-gate errno = EINVAL; 68*7c478bd9Sstevel@tonic-gate return (-1); 69*7c478bd9Sstevel@tonic-gate } 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate *lun = atoi(sp); 72*7c478bd9Sstevel@tonic-gate return (0); 73*7c478bd9Sstevel@tonic-gate } 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate /* 76*7c478bd9Sstevel@tonic-gate * Given a single token ending with a ppa spec, return the ppa spec converted 77*7c478bd9Sstevel@tonic-gate * to a uint_t. 78*7c478bd9Sstevel@tonic-gate * 79*7c478bd9Sstevel@tonic-gate * Returns: 0 for success, nonzero if an error occurred. errno is set if 80*7c478bd9Sstevel@tonic-gate * necessary. 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate static int 83*7c478bd9Sstevel@tonic-gate getppa(const char *bp, int bpsize, uint_t *ppa) 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate char *ep = (char *)&bp[bpsize - 1]; 86*7c478bd9Sstevel@tonic-gate char *tp; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate if (isdigit(*bp) || !isdigit(*ep)) { 89*7c478bd9Sstevel@tonic-gate errno = EINVAL; 90*7c478bd9Sstevel@tonic-gate return (-1); 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate for (tp = ep; tp >= bp && isdigit(*tp); tp--) 94*7c478bd9Sstevel@tonic-gate /* Null body */; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate if (*tp == '.' || *tp == ':') { 97*7c478bd9Sstevel@tonic-gate errno = EINVAL; 98*7c478bd9Sstevel@tonic-gate return (-1); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate *ppa = atoi(tp + 1); 102*7c478bd9Sstevel@tonic-gate return (0); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * Given an ifconfig-style inet relative-path interface specification 107*7c478bd9Sstevel@tonic-gate * (e.g: hme0.foo.ip.udp:2), validate its form and decompose the contents 108*7c478bd9Sstevel@tonic-gate * into a dynamically allocated ifspec_t. 109*7c478bd9Sstevel@tonic-gate * 110*7c478bd9Sstevel@tonic-gate * Returns ifspec_t for success, NULL pointer if spec is malformed. 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate boolean_t 113*7c478bd9Sstevel@tonic-gate ifparse_ifspec(const char *ifname, ifspec_t *ifsp) 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate char *mp, *ep, *lp, *tp; 116*7c478bd9Sstevel@tonic-gate char *ifnamecp; 117*7c478bd9Sstevel@tonic-gate size_t iflen; 118*7c478bd9Sstevel@tonic-gate boolean_t have_ppa = B_FALSE; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate iflen = strlen(ifname); 121*7c478bd9Sstevel@tonic-gate if (iflen > LIFNAMSIZ) { 122*7c478bd9Sstevel@tonic-gate errno = EINVAL; 123*7c478bd9Sstevel@tonic-gate return (B_FALSE); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* snag a copy we can modify */ 127*7c478bd9Sstevel@tonic-gate ifnamecp = alloca(iflen + 1); 128*7c478bd9Sstevel@tonic-gate (void) strlcpy(ifnamecp, ifname, iflen + 1); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate ifsp->ifsp_lunvalid = B_FALSE; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* 133*7c478bd9Sstevel@tonic-gate * An interface name must have the format of: 134*7c478bd9Sstevel@tonic-gate * dev[ppa][.module[.module...][ppa]][:lun] 135*7c478bd9Sstevel@tonic-gate * 136*7c478bd9Sstevel@tonic-gate * where only one ppa may be specified e.g. ip0.foo.tun or ip.foo.tun0 137*7c478bd9Sstevel@tonic-gate * 138*7c478bd9Sstevel@tonic-gate * lun - logical unit number. 139*7c478bd9Sstevel@tonic-gate * 140*7c478bd9Sstevel@tonic-gate * Produce substrings for each grouping, starting first with modules, 141*7c478bd9Sstevel@tonic-gate * then lun, devname, and finally ppa. 142*7c478bd9Sstevel@tonic-gate */ 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* Any modules? */ 145*7c478bd9Sstevel@tonic-gate mp = strchr(ifnamecp, '.'); 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate /* Any logical units? */ 148*7c478bd9Sstevel@tonic-gate lp = strchr(ifnamecp, ':'); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate if (lp != NULL && mp != NULL && lp < mp) { 151*7c478bd9Sstevel@tonic-gate errno = EINVAL; 152*7c478bd9Sstevel@tonic-gate return (B_FALSE); 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate ifsp->ifsp_modcnt = 0; 156*7c478bd9Sstevel@tonic-gate if (mp != NULL) { 157*7c478bd9Sstevel@tonic-gate *mp++ = '\0'; 158*7c478bd9Sstevel@tonic-gate if (lp != NULL) 159*7c478bd9Sstevel@tonic-gate *lp = '\0'; 160*7c478bd9Sstevel@tonic-gate while (mp != NULL && ifsp->ifsp_modcnt <= IFSP_MAXMODS) { 161*7c478bd9Sstevel@tonic-gate if ((ep = strchr(mp, '.')) != NULL) 162*7c478bd9Sstevel@tonic-gate *ep++ = '\0'; 163*7c478bd9Sstevel@tonic-gate (void) strlcpy(ifsp->ifsp_mods[ifsp->ifsp_modcnt++], 164*7c478bd9Sstevel@tonic-gate mp, LIFNAMSIZ); 165*7c478bd9Sstevel@tonic-gate mp = ep; 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate if (lp != NULL) 168*7c478bd9Sstevel@tonic-gate *lp = ':'; 169*7c478bd9Sstevel@tonic-gate if (ifsp->ifsp_modcnt > IFSP_MAXMODS) { 170*7c478bd9Sstevel@tonic-gate errno = E2BIG; 171*7c478bd9Sstevel@tonic-gate return (B_FALSE); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate if (lp != NULL) { 176*7c478bd9Sstevel@tonic-gate if (getlun(lp, strlen(lp), &ifsp->ifsp_lun) != 0) 177*7c478bd9Sstevel@tonic-gate return (B_FALSE); 178*7c478bd9Sstevel@tonic-gate ifsp->ifsp_lunvalid = B_TRUE; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate (void) strlcpy(ifsp->ifsp_devnm, ifnamecp, LIFNAMSIZ); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* Find ppa - has to be part of devname or part of last module name */ 184*7c478bd9Sstevel@tonic-gate /* This should be changed to require the latter of the two */ 185*7c478bd9Sstevel@tonic-gate if (getppa(ifsp->ifsp_devnm, strlen(ifsp->ifsp_devnm), 186*7c478bd9Sstevel@tonic-gate &ifsp->ifsp_ppa) == 0) 187*7c478bd9Sstevel@tonic-gate have_ppa = B_TRUE; 188*7c478bd9Sstevel@tonic-gate if (ifsp->ifsp_modcnt != 0 && 189*7c478bd9Sstevel@tonic-gate getppa(ifsp->ifsp_mods[ifsp->ifsp_modcnt - 1], 190*7c478bd9Sstevel@tonic-gate strlen(ifsp->ifsp_mods[ifsp->ifsp_modcnt - 1]), 191*7c478bd9Sstevel@tonic-gate &ifsp->ifsp_ppa) == 0) { 192*7c478bd9Sstevel@tonic-gate if (!have_ppa) 193*7c478bd9Sstevel@tonic-gate have_ppa = B_TRUE; 194*7c478bd9Sstevel@tonic-gate else 195*7c478bd9Sstevel@tonic-gate return (B_FALSE); /* only one please */ 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate if (!have_ppa) 198*7c478bd9Sstevel@tonic-gate return (B_FALSE); 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate /* strip the ppa off of the device name if present */ 201*7c478bd9Sstevel@tonic-gate for (tp = &ifsp->ifsp_devnm[strlen(ifsp->ifsp_devnm) - 1]; 202*7c478bd9Sstevel@tonic-gate tp >= ifsp->ifsp_devnm && isdigit(*tp); tp--) 203*7c478bd9Sstevel@tonic-gate *tp = '\0'; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate return (B_TRUE); 206*7c478bd9Sstevel@tonic-gate } 207