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