145916cd2Sjpk /* 245916cd2Sjpk * CDDL HEADER START 345916cd2Sjpk * 445916cd2Sjpk * The contents of this file are subject to the terms of the 545916cd2Sjpk * Common Development and Distribution License (the "License"). 645916cd2Sjpk * You may not use this file except in compliance with the License. 745916cd2Sjpk * 845916cd2Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 945916cd2Sjpk * or http://www.opensolaris.org/os/licensing. 1045916cd2Sjpk * See the License for the specific language governing permissions 1145916cd2Sjpk * and limitations under the License. 1245916cd2Sjpk * 1345916cd2Sjpk * When distributing Covered Code, include this CDDL HEADER in each 1445916cd2Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1545916cd2Sjpk * If applicable, add the following below this CDDL HEADER, with the 1645916cd2Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 1745916cd2Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 1845916cd2Sjpk * 1945916cd2Sjpk * CDDL HEADER END 2045916cd2Sjpk */ 2145916cd2Sjpk /* 2245916cd2Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2345916cd2Sjpk * Use is subject to license terms. 2445916cd2Sjpk * 2545916cd2Sjpk * From "misc.c 5.15 00/05/31 SMI; TSOL 2.x" 2645916cd2Sjpk */ 2745916cd2Sjpk 2845916cd2Sjpk #pragma ident "%Z%%M% %I% %E% SMI" 2945916cd2Sjpk 3045916cd2Sjpk /* 3145916cd2Sjpk * Miscellaneous user interfaces to trusted label functions. 3245916cd2Sjpk */ 3345916cd2Sjpk 3445916cd2Sjpk 3545916cd2Sjpk #include <ctype.h> 3645916cd2Sjpk #include <stdio.h> 3745916cd2Sjpk #include <stdlib.h> 3845916cd2Sjpk #include <strings.h> 3945916cd2Sjpk #include <errno.h> 4045916cd2Sjpk #include <libintl.h> 4145916cd2Sjpk #include <libtsnet.h> 4245916cd2Sjpk #include <tsol/label.h> 4345916cd2Sjpk 4445916cd2Sjpk #include <net/route.h> 4545916cd2Sjpk 4645916cd2Sjpk #define MAX_STRING_SIZE 256 4745916cd2Sjpk #define MAX_ATTR_LEN 1024 4845916cd2Sjpk 4945916cd2Sjpk /* 5045916cd2Sjpk * Parse off an entry from a line. Entry is stored in 'outbuf'. Returned 5145916cd2Sjpk * value is a pointer to the first unprocessed input character from 'instr'. 5245916cd2Sjpk */ 5345916cd2Sjpk const char * 5445916cd2Sjpk parse_entry(char *outbuf, size_t outlen, const char *instr, 5545916cd2Sjpk const char *delimit) 5645916cd2Sjpk { 5745916cd2Sjpk boolean_t escape_state = B_FALSE; 5845916cd2Sjpk boolean_t any_white; 5945916cd2Sjpk char chr; 6045916cd2Sjpk 6145916cd2Sjpk any_white = strchr(delimit, '\n') != NULL; 6245916cd2Sjpk 6345916cd2Sjpk /* 6445916cd2Sjpk * User may specify outlen as 0 to skip over a field without storing 6545916cd2Sjpk * it anywhere. Otherwise, we need at least one byte for the 6645916cd2Sjpk * terminating NUL plus one byte to store another byte from instr. 6745916cd2Sjpk */ 6845916cd2Sjpk while (outlen != 1 && (chr = *instr++) != '\0') { 6945916cd2Sjpk if (!escape_state) { 7045916cd2Sjpk if (chr == '\\') { 7145916cd2Sjpk escape_state = B_TRUE; 7245916cd2Sjpk continue; 7345916cd2Sjpk } 7445916cd2Sjpk if (strchr(delimit, chr) != NULL) 7545916cd2Sjpk break; 7645916cd2Sjpk if (any_white && isspace(chr)) 7745916cd2Sjpk break; 7845916cd2Sjpk } 7945916cd2Sjpk escape_state = B_FALSE; 8045916cd2Sjpk if (outlen > 0) { 8145916cd2Sjpk *outbuf++ = chr; 8245916cd2Sjpk outlen--; 8345916cd2Sjpk } 8445916cd2Sjpk } 8545916cd2Sjpk if (outlen != 1) 8645916cd2Sjpk instr--; 8745916cd2Sjpk if (escape_state) 8845916cd2Sjpk instr--; 8945916cd2Sjpk if (outlen > 0) 9045916cd2Sjpk *outbuf = '\0'; 9145916cd2Sjpk return (instr); 9245916cd2Sjpk } 9345916cd2Sjpk 9445916cd2Sjpk const char * 9545916cd2Sjpk sl_to_str(const bslabel_t *sl) 9645916cd2Sjpk { 9745916cd2Sjpk const char *sl_str; 9845916cd2Sjpk static const char unknown_str[] = "UNKNOWN"; 9945916cd2Sjpk 10045916cd2Sjpk if (sl == NULL) 10145916cd2Sjpk return (unknown_str); 10245916cd2Sjpk 10345916cd2Sjpk if ((sl_str = sbsltos(sl, MAX_STRING_SIZE)) == NULL && 10445916cd2Sjpk (sl_str = bsltoh(sl)) == NULL) 10545916cd2Sjpk sl_str = unknown_str; 10645916cd2Sjpk return (sl_str); 10745916cd2Sjpk } 10845916cd2Sjpk 10945916cd2Sjpk static const char *rtsa_keywords[] = { 11045916cd2Sjpk #define SAK_MINSL 0 11145916cd2Sjpk "min_sl", 11245916cd2Sjpk #define SAK_MAXSL 1 11345916cd2Sjpk "max_sl", 11445916cd2Sjpk #define SAK_DOI 2 11545916cd2Sjpk "doi", 11645916cd2Sjpk #define SAK_CIPSO 3 11745916cd2Sjpk "cipso", 118*e34b0294Swy83408 #define SAK_SL 4 119*e34b0294Swy83408 "sl", 120*e34b0294Swy83408 #define SAK_INVAL 5 12145916cd2Sjpk NULL 12245916cd2Sjpk }; 12345916cd2Sjpk 12445916cd2Sjpk const char * 12545916cd2Sjpk rtsa_to_str(const struct rtsa_s *rtsa, char *line, size_t len) 12645916cd2Sjpk { 12745916cd2Sjpk size_t slen; 12845916cd2Sjpk uint32_t mask, i; 12945916cd2Sjpk 13045916cd2Sjpk slen = 0; 13145916cd2Sjpk *line = '\0'; 13245916cd2Sjpk mask = rtsa->rtsa_mask; 13345916cd2Sjpk 13445916cd2Sjpk for (i = 1; mask != 0 && i != 0 && slen < len - 1; i <<= 1) { 13545916cd2Sjpk if (!(i & (RTSA_MINSL|RTSA_MAXSL|RTSA_DOI|RTSA_CIPSO))) 13645916cd2Sjpk continue; 13745916cd2Sjpk if (!(i & mask)) 13845916cd2Sjpk continue; 13945916cd2Sjpk if (slen != 0) 14045916cd2Sjpk line[slen++] = ','; 14145916cd2Sjpk switch (i & mask) { 14245916cd2Sjpk case RTSA_MINSL: 143*e34b0294Swy83408 if ((mask & RTSA_MAXSL) && 144*e34b0294Swy83408 blequal(&rtsa->rtsa_slrange.lower_bound, 145*e34b0294Swy83408 &rtsa->rtsa_slrange.upper_bound)) { 146*e34b0294Swy83408 slen += snprintf(line + slen, len - slen, 147*e34b0294Swy83408 "sl=%s", 148*e34b0294Swy83408 sl_to_str(&rtsa->rtsa_slrange.lower_bound)); 149*e34b0294Swy83408 mask ^= RTSA_MAXSL; 150*e34b0294Swy83408 break; 151*e34b0294Swy83408 } 15245916cd2Sjpk slen += snprintf(line + slen, len - slen, "min_sl=%s", 15345916cd2Sjpk sl_to_str(&rtsa->rtsa_slrange.lower_bound)); 15445916cd2Sjpk break; 15545916cd2Sjpk case RTSA_MAXSL: 15645916cd2Sjpk slen += snprintf(line + slen, len - slen, "max_sl=%s", 15745916cd2Sjpk sl_to_str(&rtsa->rtsa_slrange.upper_bound)); 15845916cd2Sjpk break; 15945916cd2Sjpk case RTSA_DOI: 16045916cd2Sjpk slen += snprintf(line + slen, len - slen, "doi=%d", 16145916cd2Sjpk rtsa->rtsa_doi); 16245916cd2Sjpk break; 16345916cd2Sjpk case RTSA_CIPSO: 16445916cd2Sjpk slen += snprintf(line + slen, len - slen, "cipso"); 16545916cd2Sjpk break; 16645916cd2Sjpk } 16745916cd2Sjpk } 16845916cd2Sjpk 16945916cd2Sjpk return (line); 17045916cd2Sjpk } 17145916cd2Sjpk 17245916cd2Sjpk boolean_t 17345916cd2Sjpk rtsa_keyword(const char *options, struct rtsa_s *sp, int *errp, char **errstrp) 17445916cd2Sjpk { 17545916cd2Sjpk const char *valptr, *nxtopt; 17645916cd2Sjpk uint32_t mask = 0, doi; 17745916cd2Sjpk int key; 17845916cd2Sjpk bslabel_t min_sl, max_sl; 17945916cd2Sjpk char attrbuf[MAX_ATTR_LEN]; 18045916cd2Sjpk const char **keyword; 18145916cd2Sjpk int err; 18245916cd2Sjpk char *errstr, *cp; 18345916cd2Sjpk 18445916cd2Sjpk if (errp == NULL) 18545916cd2Sjpk errp = &err; 18645916cd2Sjpk if (errstrp == NULL) 18745916cd2Sjpk errstrp = &errstr; 18845916cd2Sjpk 18945916cd2Sjpk *errstrp = (char *)options; 19045916cd2Sjpk 19145916cd2Sjpk while (*options != '\0') { 19245916cd2Sjpk valptr = parse_entry(attrbuf, sizeof (attrbuf), options, ",="); 19345916cd2Sjpk 19445916cd2Sjpk if (attrbuf[0] == '\0') { 19545916cd2Sjpk *errstrp = (char *)options; 19645916cd2Sjpk *errp = LTSNET_ILL_ENTRY; 19745916cd2Sjpk return (B_FALSE); 19845916cd2Sjpk } 19945916cd2Sjpk for (keyword = rtsa_keywords; *keyword != NULL; keyword++) 20045916cd2Sjpk if (strcmp(*keyword, attrbuf) == 0) 20145916cd2Sjpk break; 20245916cd2Sjpk if ((key = keyword - rtsa_keywords) == SAK_INVAL) { 20345916cd2Sjpk *errstrp = (char *)options; 20445916cd2Sjpk *errp = LTSNET_ILL_KEY; 20545916cd2Sjpk return (B_FALSE); 20645916cd2Sjpk } 20745916cd2Sjpk if ((key == SAK_CIPSO && *valptr == '=') || 20845916cd2Sjpk (key != SAK_CIPSO && *valptr != '=')) { 20945916cd2Sjpk *errstrp = (char *)valptr; 21045916cd2Sjpk *errp = LTSNET_ILL_VALDELIM; 21145916cd2Sjpk return (B_FALSE); 21245916cd2Sjpk } 21345916cd2Sjpk 21445916cd2Sjpk nxtopt = valptr; 21545916cd2Sjpk if (*valptr == '=') { 21645916cd2Sjpk valptr++; 21745916cd2Sjpk nxtopt = parse_entry(attrbuf, sizeof (attrbuf), 21845916cd2Sjpk valptr, ",="); 21945916cd2Sjpk if (*nxtopt == '=') { 22045916cd2Sjpk *errstrp = (char *)nxtopt; 22145916cd2Sjpk *errp = LTSNET_ILL_KEYDELIM; 22245916cd2Sjpk return (B_FALSE); 22345916cd2Sjpk } 22445916cd2Sjpk } 22545916cd2Sjpk if (*nxtopt == ',') 22645916cd2Sjpk nxtopt++; 22745916cd2Sjpk 22845916cd2Sjpk switch (key) { 22945916cd2Sjpk case SAK_MINSL: 23045916cd2Sjpk if (mask & RTSA_MINSL) { 23145916cd2Sjpk *errstrp = (char *)options; 23245916cd2Sjpk *errp = LTSNET_DUP_KEY; 23345916cd2Sjpk return (B_FALSE); 23445916cd2Sjpk } 23545916cd2Sjpk if (stobsl(attrbuf, &min_sl, NO_CORRECTION, 23645916cd2Sjpk &err) != 1) { 23745916cd2Sjpk *errstrp = (char *)valptr; 23845916cd2Sjpk *errp = LTSNET_ILL_LOWERBOUND; 23945916cd2Sjpk return (B_FALSE); 24045916cd2Sjpk } 24145916cd2Sjpk mask |= RTSA_MINSL; 24245916cd2Sjpk break; 24345916cd2Sjpk 24445916cd2Sjpk case SAK_MAXSL: 24545916cd2Sjpk if (mask & RTSA_MAXSL) { 24645916cd2Sjpk *errstrp = (char *)options; 24745916cd2Sjpk *errp = LTSNET_DUP_KEY; 24845916cd2Sjpk return (B_FALSE); 24945916cd2Sjpk } 25045916cd2Sjpk if (stobsl(attrbuf, &max_sl, NO_CORRECTION, 25145916cd2Sjpk &err) != 1) { 25245916cd2Sjpk *errstrp = (char *)valptr; 25345916cd2Sjpk *errp = LTSNET_ILL_UPPERBOUND; 25445916cd2Sjpk return (B_FALSE); 25545916cd2Sjpk } 25645916cd2Sjpk mask |= RTSA_MAXSL; 25745916cd2Sjpk break; 25845916cd2Sjpk 259*e34b0294Swy83408 case SAK_SL: 260*e34b0294Swy83408 if (mask & (RTSA_MAXSL|RTSA_MINSL)) { 261*e34b0294Swy83408 *errstrp = (char *)options; 262*e34b0294Swy83408 *errp = LTSNET_DUP_KEY; 263*e34b0294Swy83408 return (B_FALSE); 264*e34b0294Swy83408 } 265*e34b0294Swy83408 if (stobsl(attrbuf, &min_sl, NO_CORRECTION, 266*e34b0294Swy83408 &err) != 1) { 267*e34b0294Swy83408 *errstrp = (char *)valptr; 268*e34b0294Swy83408 *errp = LTSNET_ILL_LABEL; 269*e34b0294Swy83408 return (B_FALSE); 270*e34b0294Swy83408 } 271*e34b0294Swy83408 bcopy(&min_sl, &max_sl, sizeof (bslabel_t)); 272*e34b0294Swy83408 mask |= (RTSA_MINSL | RTSA_MAXSL); 273*e34b0294Swy83408 break; 274*e34b0294Swy83408 27545916cd2Sjpk case SAK_DOI: 27645916cd2Sjpk if (mask & RTSA_DOI) { 27745916cd2Sjpk *errstrp = (char *)options; 27845916cd2Sjpk *errp = LTSNET_DUP_KEY; 27945916cd2Sjpk return (B_FALSE); 28045916cd2Sjpk } 28145916cd2Sjpk errno = 0; 28245916cd2Sjpk doi = strtoul(attrbuf, &cp, 0); 28345916cd2Sjpk if (doi == 0 || errno != 0 || *cp != '\0') { 28445916cd2Sjpk *errstrp = (char *)valptr; 28545916cd2Sjpk *errp = LTSNET_ILL_DOI; 28645916cd2Sjpk return (B_FALSE); 28745916cd2Sjpk } 28845916cd2Sjpk mask |= RTSA_DOI; 28945916cd2Sjpk break; 29045916cd2Sjpk 29145916cd2Sjpk case SAK_CIPSO: 29245916cd2Sjpk if (mask & RTSA_CIPSO) { 29345916cd2Sjpk *errstrp = (char *)options; 29445916cd2Sjpk *errp = LTSNET_DUP_KEY; 29545916cd2Sjpk return (B_FALSE); 29645916cd2Sjpk } 29745916cd2Sjpk mask |= RTSA_CIPSO; 29845916cd2Sjpk break; 29945916cd2Sjpk } 30045916cd2Sjpk 30145916cd2Sjpk options = nxtopt; 30245916cd2Sjpk } 30345916cd2Sjpk 30445916cd2Sjpk /* Defaults to CIPSO if not specified */ 30545916cd2Sjpk mask |= RTSA_CIPSO; 30645916cd2Sjpk 30745916cd2Sjpk /* If RTSA_CIPSO is specified, RTSA_DOI must be specified */ 30845916cd2Sjpk if (!(mask & RTSA_DOI)) { 30945916cd2Sjpk *errp = LTSNET_NO_DOI; 31045916cd2Sjpk return (B_FALSE); 31145916cd2Sjpk } 31245916cd2Sjpk 31345916cd2Sjpk /* SL range must be specified */ 31445916cd2Sjpk if (!(mask & (RTSA_MINSL|RTSA_MAXSL))) { 31545916cd2Sjpk *errp = LTSNET_NO_RANGE; 31645916cd2Sjpk return (B_FALSE); 31745916cd2Sjpk } 31845916cd2Sjpk if (!(mask & RTSA_MINSL)) { 31945916cd2Sjpk *errp = LTSNET_NO_LOWERBOUND; 32045916cd2Sjpk return (B_FALSE); 32145916cd2Sjpk } 32245916cd2Sjpk if (!(mask & RTSA_MAXSL)) { 32345916cd2Sjpk *errp = LTSNET_NO_UPPERBOUND; 32445916cd2Sjpk return (B_FALSE); 32545916cd2Sjpk } 32645916cd2Sjpk 32745916cd2Sjpk /* SL range must have upper bound dominating lower bound */ 32845916cd2Sjpk if (!bldominates(&max_sl, &min_sl)) { 32945916cd2Sjpk *errp = LTSNET_ILL_RANGE; 33045916cd2Sjpk return (B_FALSE); 33145916cd2Sjpk } 33245916cd2Sjpk 33345916cd2Sjpk if (mask & RTSA_MINSL) 33445916cd2Sjpk sp->rtsa_slrange.lower_bound = min_sl; 33545916cd2Sjpk if (mask & RTSA_MAXSL) 33645916cd2Sjpk sp->rtsa_slrange.upper_bound = max_sl; 33745916cd2Sjpk if (mask & RTSA_DOI) 33845916cd2Sjpk sp->rtsa_doi = doi; 33945916cd2Sjpk sp->rtsa_mask = mask; 34045916cd2Sjpk 34145916cd2Sjpk return (B_TRUE); 34245916cd2Sjpk } 34345916cd2Sjpk 34445916cd2Sjpk /* Keep in sync with libtsnet.h */ 34545916cd2Sjpk static const char *tsol_errlist[] = { 34645916cd2Sjpk "No error", 34745916cd2Sjpk "System error", 34845916cd2Sjpk "Empty string or end of list", 34945916cd2Sjpk "Entry is malformed", 35045916cd2Sjpk "Missing name", 35145916cd2Sjpk "Missing attributes", 35245916cd2Sjpk "Illegal name", 35345916cd2Sjpk "Illegal keyword delimiter", 35445916cd2Sjpk "Unknown keyword", 35545916cd2Sjpk "Duplicate keyword", 35645916cd2Sjpk "Illegal value delimiter", 35745916cd2Sjpk "Missing host type", 35845916cd2Sjpk "Illegal host type", 35945916cd2Sjpk "Missing label", 36045916cd2Sjpk "Illegal label", 36145916cd2Sjpk "Missing label range", 36245916cd2Sjpk "Illegal label range", 36345916cd2Sjpk "No lower bound in range", 36445916cd2Sjpk "Illegal lower bound in range", 36545916cd2Sjpk "No upper bound in range", 36645916cd2Sjpk "Illegal upper bound in range", 36745916cd2Sjpk "Missing DOI", 36845916cd2Sjpk "Illegal DOI", 36945916cd2Sjpk "Too many entries in set", 37045916cd2Sjpk "Missing address/network", 37145916cd2Sjpk "Illegal address/network", 37245916cd2Sjpk "Illegal flag", 37345916cd2Sjpk "Illegal MLP specification", 37445916cd2Sjpk "Unacceptable keyword for type" 37545916cd2Sjpk }; 37645916cd2Sjpk static const int tsol_nerr = sizeof (tsol_errlist) / sizeof (*tsol_errlist); 37745916cd2Sjpk 37845916cd2Sjpk const char * 37945916cd2Sjpk tsol_strerror(int libtserr, int errnoval) 38045916cd2Sjpk { 38145916cd2Sjpk if (libtserr == LTSNET_SYSERR) 38245916cd2Sjpk return (strerror(errnoval)); 38345916cd2Sjpk if (libtserr >= 0 && libtserr < tsol_nerr) 38445916cd2Sjpk return (gettext(tsol_errlist[libtserr])); 38545916cd2Sjpk return (gettext("Unknown error")); 38645916cd2Sjpk } 387