1*1676Sjpk /* 2*1676Sjpk * CDDL HEADER START 3*1676Sjpk * 4*1676Sjpk * The contents of this file are subject to the terms of the 5*1676Sjpk * Common Development and Distribution License (the "License"). 6*1676Sjpk * You may not use this file except in compliance with the License. 7*1676Sjpk * 8*1676Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1676Sjpk * or http://www.opensolaris.org/os/licensing. 10*1676Sjpk * See the License for the specific language governing permissions 11*1676Sjpk * and limitations under the License. 12*1676Sjpk * 13*1676Sjpk * When distributing Covered Code, include this CDDL HEADER in each 14*1676Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1676Sjpk * If applicable, add the following below this CDDL HEADER, with the 16*1676Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 17*1676Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 18*1676Sjpk * 19*1676Sjpk * CDDL HEADER END 20*1676Sjpk */ 21*1676Sjpk /* 22*1676Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*1676Sjpk * Use is subject to license terms. 24*1676Sjpk * 25*1676Sjpk * From "misc.c 5.15 00/05/31 SMI; TSOL 2.x" 26*1676Sjpk */ 27*1676Sjpk 28*1676Sjpk #pragma ident "%Z%%M% %I% %E% SMI" 29*1676Sjpk 30*1676Sjpk /* 31*1676Sjpk * Miscellaneous user interfaces to trusted label functions. 32*1676Sjpk */ 33*1676Sjpk 34*1676Sjpk 35*1676Sjpk #include <ctype.h> 36*1676Sjpk #include <stdio.h> 37*1676Sjpk #include <stdlib.h> 38*1676Sjpk #include <strings.h> 39*1676Sjpk #include <errno.h> 40*1676Sjpk #include <libintl.h> 41*1676Sjpk #include <libtsnet.h> 42*1676Sjpk #include <tsol/label.h> 43*1676Sjpk 44*1676Sjpk #include <net/route.h> 45*1676Sjpk 46*1676Sjpk #define MAX_STRING_SIZE 256 47*1676Sjpk #define MAX_ATTR_LEN 1024 48*1676Sjpk 49*1676Sjpk /* 50*1676Sjpk * Parse off an entry from a line. Entry is stored in 'outbuf'. Returned 51*1676Sjpk * value is a pointer to the first unprocessed input character from 'instr'. 52*1676Sjpk */ 53*1676Sjpk const char * 54*1676Sjpk parse_entry(char *outbuf, size_t outlen, const char *instr, 55*1676Sjpk const char *delimit) 56*1676Sjpk { 57*1676Sjpk boolean_t escape_state = B_FALSE; 58*1676Sjpk boolean_t any_white; 59*1676Sjpk char chr; 60*1676Sjpk 61*1676Sjpk any_white = strchr(delimit, '\n') != NULL; 62*1676Sjpk 63*1676Sjpk /* 64*1676Sjpk * User may specify outlen as 0 to skip over a field without storing 65*1676Sjpk * it anywhere. Otherwise, we need at least one byte for the 66*1676Sjpk * terminating NUL plus one byte to store another byte from instr. 67*1676Sjpk */ 68*1676Sjpk while (outlen != 1 && (chr = *instr++) != '\0') { 69*1676Sjpk if (!escape_state) { 70*1676Sjpk if (chr == '\\') { 71*1676Sjpk escape_state = B_TRUE; 72*1676Sjpk continue; 73*1676Sjpk } 74*1676Sjpk if (strchr(delimit, chr) != NULL) 75*1676Sjpk break; 76*1676Sjpk if (any_white && isspace(chr)) 77*1676Sjpk break; 78*1676Sjpk } 79*1676Sjpk escape_state = B_FALSE; 80*1676Sjpk if (outlen > 0) { 81*1676Sjpk *outbuf++ = chr; 82*1676Sjpk outlen--; 83*1676Sjpk } 84*1676Sjpk } 85*1676Sjpk if (outlen != 1) 86*1676Sjpk instr--; 87*1676Sjpk if (escape_state) 88*1676Sjpk instr--; 89*1676Sjpk if (outlen > 0) 90*1676Sjpk *outbuf = '\0'; 91*1676Sjpk return (instr); 92*1676Sjpk } 93*1676Sjpk 94*1676Sjpk const char * 95*1676Sjpk sl_to_str(const bslabel_t *sl) 96*1676Sjpk { 97*1676Sjpk const char *sl_str; 98*1676Sjpk static const char unknown_str[] = "UNKNOWN"; 99*1676Sjpk 100*1676Sjpk if (sl == NULL) 101*1676Sjpk return (unknown_str); 102*1676Sjpk 103*1676Sjpk if ((sl_str = sbsltos(sl, MAX_STRING_SIZE)) == NULL && 104*1676Sjpk (sl_str = bsltoh(sl)) == NULL) 105*1676Sjpk sl_str = unknown_str; 106*1676Sjpk return (sl_str); 107*1676Sjpk } 108*1676Sjpk 109*1676Sjpk static const char *rtsa_keywords[] = { 110*1676Sjpk #define SAK_MINSL 0 111*1676Sjpk "min_sl", 112*1676Sjpk #define SAK_MAXSL 1 113*1676Sjpk "max_sl", 114*1676Sjpk #define SAK_DOI 2 115*1676Sjpk "doi", 116*1676Sjpk #define SAK_CIPSO 3 117*1676Sjpk "cipso", 118*1676Sjpk #define SAK_INVAL 4 119*1676Sjpk NULL 120*1676Sjpk }; 121*1676Sjpk 122*1676Sjpk const char * 123*1676Sjpk rtsa_to_str(const struct rtsa_s *rtsa, char *line, size_t len) 124*1676Sjpk { 125*1676Sjpk size_t slen; 126*1676Sjpk uint32_t mask, i; 127*1676Sjpk 128*1676Sjpk slen = 0; 129*1676Sjpk *line = '\0'; 130*1676Sjpk mask = rtsa->rtsa_mask; 131*1676Sjpk 132*1676Sjpk for (i = 1; mask != 0 && i != 0 && slen < len - 1; i <<= 1) { 133*1676Sjpk if (!(i & (RTSA_MINSL|RTSA_MAXSL|RTSA_DOI|RTSA_CIPSO))) 134*1676Sjpk continue; 135*1676Sjpk if (!(i & mask)) 136*1676Sjpk continue; 137*1676Sjpk if (slen != 0) 138*1676Sjpk line[slen++] = ','; 139*1676Sjpk switch (i & mask) { 140*1676Sjpk case RTSA_MINSL: 141*1676Sjpk slen += snprintf(line + slen, len - slen, "min_sl=%s", 142*1676Sjpk sl_to_str(&rtsa->rtsa_slrange.lower_bound)); 143*1676Sjpk break; 144*1676Sjpk case RTSA_MAXSL: 145*1676Sjpk slen += snprintf(line + slen, len - slen, "max_sl=%s", 146*1676Sjpk sl_to_str(&rtsa->rtsa_slrange.upper_bound)); 147*1676Sjpk break; 148*1676Sjpk case RTSA_DOI: 149*1676Sjpk slen += snprintf(line + slen, len - slen, "doi=%d", 150*1676Sjpk rtsa->rtsa_doi); 151*1676Sjpk break; 152*1676Sjpk case RTSA_CIPSO: 153*1676Sjpk slen += snprintf(line + slen, len - slen, "cipso"); 154*1676Sjpk break; 155*1676Sjpk } 156*1676Sjpk } 157*1676Sjpk 158*1676Sjpk return (line); 159*1676Sjpk } 160*1676Sjpk 161*1676Sjpk boolean_t 162*1676Sjpk rtsa_keyword(const char *options, struct rtsa_s *sp, int *errp, char **errstrp) 163*1676Sjpk { 164*1676Sjpk const char *valptr, *nxtopt; 165*1676Sjpk uint32_t mask = 0, doi; 166*1676Sjpk int key; 167*1676Sjpk bslabel_t min_sl, max_sl; 168*1676Sjpk char attrbuf[MAX_ATTR_LEN]; 169*1676Sjpk const char **keyword; 170*1676Sjpk int err; 171*1676Sjpk char *errstr, *cp; 172*1676Sjpk 173*1676Sjpk if (errp == NULL) 174*1676Sjpk errp = &err; 175*1676Sjpk if (errstrp == NULL) 176*1676Sjpk errstrp = &errstr; 177*1676Sjpk 178*1676Sjpk *errstrp = (char *)options; 179*1676Sjpk 180*1676Sjpk while (*options != '\0') { 181*1676Sjpk valptr = parse_entry(attrbuf, sizeof (attrbuf), options, ",="); 182*1676Sjpk 183*1676Sjpk if (attrbuf[0] == '\0') { 184*1676Sjpk *errstrp = (char *)options; 185*1676Sjpk *errp = LTSNET_ILL_ENTRY; 186*1676Sjpk return (B_FALSE); 187*1676Sjpk } 188*1676Sjpk for (keyword = rtsa_keywords; *keyword != NULL; keyword++) 189*1676Sjpk if (strcmp(*keyword, attrbuf) == 0) 190*1676Sjpk break; 191*1676Sjpk if ((key = keyword - rtsa_keywords) == SAK_INVAL) { 192*1676Sjpk *errstrp = (char *)options; 193*1676Sjpk *errp = LTSNET_ILL_KEY; 194*1676Sjpk return (B_FALSE); 195*1676Sjpk } 196*1676Sjpk if ((key == SAK_CIPSO && *valptr == '=') || 197*1676Sjpk (key != SAK_CIPSO && *valptr != '=')) { 198*1676Sjpk *errstrp = (char *)valptr; 199*1676Sjpk *errp = LTSNET_ILL_VALDELIM; 200*1676Sjpk return (B_FALSE); 201*1676Sjpk } 202*1676Sjpk 203*1676Sjpk nxtopt = valptr; 204*1676Sjpk if (*valptr == '=') { 205*1676Sjpk valptr++; 206*1676Sjpk nxtopt = parse_entry(attrbuf, sizeof (attrbuf), 207*1676Sjpk valptr, ",="); 208*1676Sjpk if (*nxtopt == '=') { 209*1676Sjpk *errstrp = (char *)nxtopt; 210*1676Sjpk *errp = LTSNET_ILL_KEYDELIM; 211*1676Sjpk return (B_FALSE); 212*1676Sjpk } 213*1676Sjpk } 214*1676Sjpk if (*nxtopt == ',') 215*1676Sjpk nxtopt++; 216*1676Sjpk 217*1676Sjpk switch (key) { 218*1676Sjpk case SAK_MINSL: 219*1676Sjpk if (mask & RTSA_MINSL) { 220*1676Sjpk *errstrp = (char *)options; 221*1676Sjpk *errp = LTSNET_DUP_KEY; 222*1676Sjpk return (B_FALSE); 223*1676Sjpk } 224*1676Sjpk if (stobsl(attrbuf, &min_sl, NO_CORRECTION, 225*1676Sjpk &err) != 1) { 226*1676Sjpk *errstrp = (char *)valptr; 227*1676Sjpk *errp = LTSNET_ILL_LOWERBOUND; 228*1676Sjpk return (B_FALSE); 229*1676Sjpk } 230*1676Sjpk mask |= RTSA_MINSL; 231*1676Sjpk break; 232*1676Sjpk 233*1676Sjpk case SAK_MAXSL: 234*1676Sjpk if (mask & RTSA_MAXSL) { 235*1676Sjpk *errstrp = (char *)options; 236*1676Sjpk *errp = LTSNET_DUP_KEY; 237*1676Sjpk return (B_FALSE); 238*1676Sjpk } 239*1676Sjpk if (stobsl(attrbuf, &max_sl, NO_CORRECTION, 240*1676Sjpk &err) != 1) { 241*1676Sjpk *errstrp = (char *)valptr; 242*1676Sjpk *errp = LTSNET_ILL_UPPERBOUND; 243*1676Sjpk return (B_FALSE); 244*1676Sjpk } 245*1676Sjpk mask |= RTSA_MAXSL; 246*1676Sjpk break; 247*1676Sjpk 248*1676Sjpk case SAK_DOI: 249*1676Sjpk if (mask & RTSA_DOI) { 250*1676Sjpk *errstrp = (char *)options; 251*1676Sjpk *errp = LTSNET_DUP_KEY; 252*1676Sjpk return (B_FALSE); 253*1676Sjpk } 254*1676Sjpk errno = 0; 255*1676Sjpk doi = strtoul(attrbuf, &cp, 0); 256*1676Sjpk if (doi == 0 || errno != 0 || *cp != '\0') { 257*1676Sjpk *errstrp = (char *)valptr; 258*1676Sjpk *errp = LTSNET_ILL_DOI; 259*1676Sjpk return (B_FALSE); 260*1676Sjpk } 261*1676Sjpk mask |= RTSA_DOI; 262*1676Sjpk break; 263*1676Sjpk 264*1676Sjpk case SAK_CIPSO: 265*1676Sjpk if (mask & RTSA_CIPSO) { 266*1676Sjpk *errstrp = (char *)options; 267*1676Sjpk *errp = LTSNET_DUP_KEY; 268*1676Sjpk return (B_FALSE); 269*1676Sjpk } 270*1676Sjpk mask |= RTSA_CIPSO; 271*1676Sjpk break; 272*1676Sjpk } 273*1676Sjpk 274*1676Sjpk options = nxtopt; 275*1676Sjpk } 276*1676Sjpk 277*1676Sjpk /* Defaults to CIPSO if not specified */ 278*1676Sjpk mask |= RTSA_CIPSO; 279*1676Sjpk 280*1676Sjpk /* If RTSA_CIPSO is specified, RTSA_DOI must be specified */ 281*1676Sjpk if (!(mask & RTSA_DOI)) { 282*1676Sjpk *errp = LTSNET_NO_DOI; 283*1676Sjpk return (B_FALSE); 284*1676Sjpk } 285*1676Sjpk 286*1676Sjpk /* SL range must be specified */ 287*1676Sjpk if (!(mask & (RTSA_MINSL|RTSA_MAXSL))) { 288*1676Sjpk *errp = LTSNET_NO_RANGE; 289*1676Sjpk return (B_FALSE); 290*1676Sjpk } 291*1676Sjpk if (!(mask & RTSA_MINSL)) { 292*1676Sjpk *errp = LTSNET_NO_LOWERBOUND; 293*1676Sjpk return (B_FALSE); 294*1676Sjpk } 295*1676Sjpk if (!(mask & RTSA_MAXSL)) { 296*1676Sjpk *errp = LTSNET_NO_UPPERBOUND; 297*1676Sjpk return (B_FALSE); 298*1676Sjpk } 299*1676Sjpk 300*1676Sjpk /* SL range must have upper bound dominating lower bound */ 301*1676Sjpk if (!bldominates(&max_sl, &min_sl)) { 302*1676Sjpk *errp = LTSNET_ILL_RANGE; 303*1676Sjpk return (B_FALSE); 304*1676Sjpk } 305*1676Sjpk 306*1676Sjpk if (mask & RTSA_MINSL) 307*1676Sjpk sp->rtsa_slrange.lower_bound = min_sl; 308*1676Sjpk if (mask & RTSA_MAXSL) 309*1676Sjpk sp->rtsa_slrange.upper_bound = max_sl; 310*1676Sjpk if (mask & RTSA_DOI) 311*1676Sjpk sp->rtsa_doi = doi; 312*1676Sjpk sp->rtsa_mask = mask; 313*1676Sjpk 314*1676Sjpk return (B_TRUE); 315*1676Sjpk } 316*1676Sjpk 317*1676Sjpk /* Keep in sync with libtsnet.h */ 318*1676Sjpk static const char *tsol_errlist[] = { 319*1676Sjpk "No error", 320*1676Sjpk "System error", 321*1676Sjpk "Empty string or end of list", 322*1676Sjpk "Entry is malformed", 323*1676Sjpk "Missing name", 324*1676Sjpk "Missing attributes", 325*1676Sjpk "Illegal name", 326*1676Sjpk "Illegal keyword delimiter", 327*1676Sjpk "Unknown keyword", 328*1676Sjpk "Duplicate keyword", 329*1676Sjpk "Illegal value delimiter", 330*1676Sjpk "Missing host type", 331*1676Sjpk "Illegal host type", 332*1676Sjpk "Missing label", 333*1676Sjpk "Illegal label", 334*1676Sjpk "Missing label range", 335*1676Sjpk "Illegal label range", 336*1676Sjpk "No lower bound in range", 337*1676Sjpk "Illegal lower bound in range", 338*1676Sjpk "No upper bound in range", 339*1676Sjpk "Illegal upper bound in range", 340*1676Sjpk "Missing DOI", 341*1676Sjpk "Illegal DOI", 342*1676Sjpk "Too many entries in set", 343*1676Sjpk "Missing address/network", 344*1676Sjpk "Illegal address/network", 345*1676Sjpk "Illegal flag", 346*1676Sjpk "Illegal MLP specification", 347*1676Sjpk "Unacceptable keyword for type" 348*1676Sjpk }; 349*1676Sjpk static const int tsol_nerr = sizeof (tsol_errlist) / sizeof (*tsol_errlist); 350*1676Sjpk 351*1676Sjpk const char * 352*1676Sjpk tsol_strerror(int libtserr, int errnoval) 353*1676Sjpk { 354*1676Sjpk if (libtserr == LTSNET_SYSERR) 355*1676Sjpk return (strerror(errnoval)); 356*1676Sjpk if (libtserr >= 0 && libtserr < tsol_nerr) 357*1676Sjpk return (gettext(tsol_errlist[libtserr])); 358*1676Sjpk return (gettext("Unknown error")); 359*1676Sjpk } 360