10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53628Sss150715 * Common Development and Distribution License (the "License"). 63628Sss150715 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*10616SSebastien.Roy@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 233628Sss150715 * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * This file contains a routine used to validate a ifconfig-style interface 280Sstevel@tonic-gate * specification 290Sstevel@tonic-gate */ 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include <stdlib.h> 320Sstevel@tonic-gate #include <ctype.h> 330Sstevel@tonic-gate #include <alloca.h> 340Sstevel@tonic-gate #include <errno.h> 350Sstevel@tonic-gate #include <string.h> 360Sstevel@tonic-gate #include <libinetutil.h> 370Sstevel@tonic-gate 380Sstevel@tonic-gate /* 390Sstevel@tonic-gate * Given a token with a logical unit spec, return the logical unit converted 400Sstevel@tonic-gate * to a uint_t. 410Sstevel@tonic-gate * 420Sstevel@tonic-gate * Returns: 0 for success, nonzero if an error occurred. errno is set if 430Sstevel@tonic-gate * necessary. 440Sstevel@tonic-gate */ 450Sstevel@tonic-gate static int 460Sstevel@tonic-gate getlun(const char *bp, int bpsize, uint_t *lun) 470Sstevel@tonic-gate { 480Sstevel@tonic-gate char *ep = (char *)&bp[bpsize - 1]; 490Sstevel@tonic-gate char *sp = strchr(bp, ':'), *tp; 500Sstevel@tonic-gate 510Sstevel@tonic-gate /* A logical unit spec looks like: <token>:<unsigned int>\0 */ 520Sstevel@tonic-gate if (isdigit(*bp) || !isdigit(*ep) || sp == NULL || 530Sstevel@tonic-gate strchr(sp + 1, ':') != NULL) { 540Sstevel@tonic-gate errno = EINVAL; 550Sstevel@tonic-gate return (-1); 560Sstevel@tonic-gate } 570Sstevel@tonic-gate 580Sstevel@tonic-gate *sp++ = '\0'; 590Sstevel@tonic-gate 600Sstevel@tonic-gate /* Lun must be all digits */ 610Sstevel@tonic-gate for (tp = sp; tp < ep && isdigit(*tp); tp++) 620Sstevel@tonic-gate /* Null body */; 630Sstevel@tonic-gate if (tp != ep) { 640Sstevel@tonic-gate errno = EINVAL; 650Sstevel@tonic-gate return (-1); 660Sstevel@tonic-gate } 670Sstevel@tonic-gate 680Sstevel@tonic-gate *lun = atoi(sp); 690Sstevel@tonic-gate return (0); 700Sstevel@tonic-gate } 710Sstevel@tonic-gate 720Sstevel@tonic-gate /* 730Sstevel@tonic-gate * Given a single token ending with a ppa spec, return the ppa spec converted 740Sstevel@tonic-gate * to a uint_t. 750Sstevel@tonic-gate * 760Sstevel@tonic-gate * Returns: 0 for success, nonzero if an error occurred. errno is set if 770Sstevel@tonic-gate * necessary. 780Sstevel@tonic-gate */ 790Sstevel@tonic-gate static int 800Sstevel@tonic-gate getppa(const char *bp, int bpsize, uint_t *ppa) 810Sstevel@tonic-gate { 820Sstevel@tonic-gate char *ep = (char *)&bp[bpsize - 1]; 830Sstevel@tonic-gate char *tp; 840Sstevel@tonic-gate 853628Sss150715 if (!isdigit(*ep)) { 860Sstevel@tonic-gate errno = EINVAL; 870Sstevel@tonic-gate return (-1); 880Sstevel@tonic-gate } 890Sstevel@tonic-gate 900Sstevel@tonic-gate for (tp = ep; tp >= bp && isdigit(*tp); tp--) 910Sstevel@tonic-gate /* Null body */; 920Sstevel@tonic-gate 93*10616SSebastien.Roy@Sun.COM if (*tp == ':') { 940Sstevel@tonic-gate errno = EINVAL; 950Sstevel@tonic-gate return (-1); 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate *ppa = atoi(tp + 1); 990Sstevel@tonic-gate return (0); 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* 1030Sstevel@tonic-gate * Given an ifconfig-style inet relative-path interface specification 104*10616SSebastien.Roy@Sun.COM * (e.g: bge0:2), validate its form and decompose the contents into a 105*10616SSebastien.Roy@Sun.COM * dynamically allocated ifspec_t. 1060Sstevel@tonic-gate * 1070Sstevel@tonic-gate * Returns ifspec_t for success, NULL pointer if spec is malformed. 1080Sstevel@tonic-gate */ 1090Sstevel@tonic-gate boolean_t 1100Sstevel@tonic-gate ifparse_ifspec(const char *ifname, ifspec_t *ifsp) 1110Sstevel@tonic-gate { 112*10616SSebastien.Roy@Sun.COM char *lp, *tp; 113*10616SSebastien.Roy@Sun.COM char ifnamecp[LIFNAMSIZ]; 1140Sstevel@tonic-gate 115*10616SSebastien.Roy@Sun.COM /* snag a copy we can modify */ 116*10616SSebastien.Roy@Sun.COM if (strlcpy(ifnamecp, ifname, LIFNAMSIZ) >= LIFNAMSIZ) { 1170Sstevel@tonic-gate errno = EINVAL; 1180Sstevel@tonic-gate return (B_FALSE); 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate ifsp->ifsp_lunvalid = B_FALSE; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate /* 1240Sstevel@tonic-gate * An interface name must have the format of: 125*10616SSebastien.Roy@Sun.COM * dev[ppa][:lun] 1260Sstevel@tonic-gate * 1270Sstevel@tonic-gate * lun - logical unit number. 1280Sstevel@tonic-gate */ 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate /* Any logical units? */ 1310Sstevel@tonic-gate lp = strchr(ifnamecp, ':'); 1320Sstevel@tonic-gate if (lp != NULL) { 1330Sstevel@tonic-gate if (getlun(lp, strlen(lp), &ifsp->ifsp_lun) != 0) 1340Sstevel@tonic-gate return (B_FALSE); 1350Sstevel@tonic-gate ifsp->ifsp_lunvalid = B_TRUE; 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate (void) strlcpy(ifsp->ifsp_devnm, ifnamecp, LIFNAMSIZ); 1390Sstevel@tonic-gate 140*10616SSebastien.Roy@Sun.COM /* Find ppa */ 141*10616SSebastien.Roy@Sun.COM if (getppa(ifsp->ifsp_devnm, strlen(ifsp->ifsp_devnm), 142*10616SSebastien.Roy@Sun.COM &ifsp->ifsp_ppa) != 0) { 143*10616SSebastien.Roy@Sun.COM return (B_FALSE); 1443628Sss150715 } 1450Sstevel@tonic-gate 146*10616SSebastien.Roy@Sun.COM /* strip the ppa off of the device name if present */ 147*10616SSebastien.Roy@Sun.COM for (tp = &ifsp->ifsp_devnm[strlen(ifsp->ifsp_devnm) - 1]; 148*10616SSebastien.Roy@Sun.COM tp >= ifsp->ifsp_devnm && isdigit(*tp); tp--) { 149*10616SSebastien.Roy@Sun.COM *tp = '\0'; 150*10616SSebastien.Roy@Sun.COM } 151*10616SSebastien.Roy@Sun.COM 152*10616SSebastien.Roy@Sun.COM return (B_TRUE); 1530Sstevel@tonic-gate } 154