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_SL 4 119 "sl", 120 #define SAK_INVAL 5 121 NULL 122 }; 123 124 const char * 125 rtsa_to_str(const struct rtsa_s *rtsa, char *line, size_t len) 126 { 127 size_t slen; 128 uint32_t mask, i; 129 130 slen = 0; 131 *line = '\0'; 132 mask = rtsa->rtsa_mask; 133 134 for (i = 1; mask != 0 && i != 0 && slen < len - 1; i <<= 1) { 135 if (!(i & (RTSA_MINSL|RTSA_MAXSL|RTSA_DOI|RTSA_CIPSO))) 136 continue; 137 if (!(i & mask)) 138 continue; 139 if (slen != 0) 140 line[slen++] = ','; 141 switch (i & mask) { 142 case RTSA_MINSL: 143 if ((mask & RTSA_MAXSL) && 144 blequal(&rtsa->rtsa_slrange.lower_bound, 145 &rtsa->rtsa_slrange.upper_bound)) { 146 slen += snprintf(line + slen, len - slen, 147 "sl=%s", 148 sl_to_str(&rtsa->rtsa_slrange.lower_bound)); 149 mask ^= RTSA_MAXSL; 150 break; 151 } 152 slen += snprintf(line + slen, len - slen, "min_sl=%s", 153 sl_to_str(&rtsa->rtsa_slrange.lower_bound)); 154 break; 155 case RTSA_MAXSL: 156 slen += snprintf(line + slen, len - slen, "max_sl=%s", 157 sl_to_str(&rtsa->rtsa_slrange.upper_bound)); 158 break; 159 case RTSA_DOI: 160 slen += snprintf(line + slen, len - slen, "doi=%d", 161 rtsa->rtsa_doi); 162 break; 163 case RTSA_CIPSO: 164 slen += snprintf(line + slen, len - slen, "cipso"); 165 break; 166 } 167 } 168 169 return (line); 170 } 171 172 boolean_t 173 rtsa_keyword(const char *options, struct rtsa_s *sp, int *errp, char **errstrp) 174 { 175 const char *valptr, *nxtopt; 176 uint32_t mask = 0, doi; 177 int key; 178 bslabel_t min_sl, max_sl; 179 char attrbuf[MAX_ATTR_LEN]; 180 const char **keyword; 181 int err; 182 char *errstr, *cp; 183 184 if (errp == NULL) 185 errp = &err; 186 if (errstrp == NULL) 187 errstrp = &errstr; 188 189 *errstrp = (char *)options; 190 191 while (*options != '\0') { 192 valptr = parse_entry(attrbuf, sizeof (attrbuf), options, ",="); 193 194 if (attrbuf[0] == '\0') { 195 *errstrp = (char *)options; 196 *errp = LTSNET_ILL_ENTRY; 197 return (B_FALSE); 198 } 199 for (keyword = rtsa_keywords; *keyword != NULL; keyword++) 200 if (strcmp(*keyword, attrbuf) == 0) 201 break; 202 if ((key = keyword - rtsa_keywords) == SAK_INVAL) { 203 *errstrp = (char *)options; 204 *errp = LTSNET_ILL_KEY; 205 return (B_FALSE); 206 } 207 if ((key == SAK_CIPSO && *valptr == '=') || 208 (key != SAK_CIPSO && *valptr != '=')) { 209 *errstrp = (char *)valptr; 210 *errp = LTSNET_ILL_VALDELIM; 211 return (B_FALSE); 212 } 213 214 nxtopt = valptr; 215 if (*valptr == '=') { 216 valptr++; 217 nxtopt = parse_entry(attrbuf, sizeof (attrbuf), 218 valptr, ",="); 219 if (*nxtopt == '=') { 220 *errstrp = (char *)nxtopt; 221 *errp = LTSNET_ILL_KEYDELIM; 222 return (B_FALSE); 223 } 224 } 225 if (*nxtopt == ',') 226 nxtopt++; 227 228 switch (key) { 229 case SAK_MINSL: 230 if (mask & RTSA_MINSL) { 231 *errstrp = (char *)options; 232 *errp = LTSNET_DUP_KEY; 233 return (B_FALSE); 234 } 235 if (stobsl(attrbuf, &min_sl, NO_CORRECTION, 236 &err) != 1) { 237 *errstrp = (char *)valptr; 238 *errp = LTSNET_ILL_LOWERBOUND; 239 return (B_FALSE); 240 } 241 mask |= RTSA_MINSL; 242 break; 243 244 case SAK_MAXSL: 245 if (mask & RTSA_MAXSL) { 246 *errstrp = (char *)options; 247 *errp = LTSNET_DUP_KEY; 248 return (B_FALSE); 249 } 250 if (stobsl(attrbuf, &max_sl, NO_CORRECTION, 251 &err) != 1) { 252 *errstrp = (char *)valptr; 253 *errp = LTSNET_ILL_UPPERBOUND; 254 return (B_FALSE); 255 } 256 mask |= RTSA_MAXSL; 257 break; 258 259 case SAK_SL: 260 if (mask & (RTSA_MAXSL|RTSA_MINSL)) { 261 *errstrp = (char *)options; 262 *errp = LTSNET_DUP_KEY; 263 return (B_FALSE); 264 } 265 if (stobsl(attrbuf, &min_sl, NO_CORRECTION, 266 &err) != 1) { 267 *errstrp = (char *)valptr; 268 *errp = LTSNET_ILL_LABEL; 269 return (B_FALSE); 270 } 271 bcopy(&min_sl, &max_sl, sizeof (bslabel_t)); 272 mask |= (RTSA_MINSL | RTSA_MAXSL); 273 break; 274 275 case SAK_DOI: 276 if (mask & RTSA_DOI) { 277 *errstrp = (char *)options; 278 *errp = LTSNET_DUP_KEY; 279 return (B_FALSE); 280 } 281 errno = 0; 282 doi = strtoul(attrbuf, &cp, 0); 283 if (doi == 0 || errno != 0 || *cp != '\0') { 284 *errstrp = (char *)valptr; 285 *errp = LTSNET_ILL_DOI; 286 return (B_FALSE); 287 } 288 mask |= RTSA_DOI; 289 break; 290 291 case SAK_CIPSO: 292 if (mask & RTSA_CIPSO) { 293 *errstrp = (char *)options; 294 *errp = LTSNET_DUP_KEY; 295 return (B_FALSE); 296 } 297 mask |= RTSA_CIPSO; 298 break; 299 } 300 301 options = nxtopt; 302 } 303 304 /* Defaults to CIPSO if not specified */ 305 mask |= RTSA_CIPSO; 306 307 /* If RTSA_CIPSO is specified, RTSA_DOI must be specified */ 308 if (!(mask & RTSA_DOI)) { 309 *errp = LTSNET_NO_DOI; 310 return (B_FALSE); 311 } 312 313 /* SL range must be specified */ 314 if (!(mask & (RTSA_MINSL|RTSA_MAXSL))) { 315 *errp = LTSNET_NO_RANGE; 316 return (B_FALSE); 317 } 318 if (!(mask & RTSA_MINSL)) { 319 *errp = LTSNET_NO_LOWERBOUND; 320 return (B_FALSE); 321 } 322 if (!(mask & RTSA_MAXSL)) { 323 *errp = LTSNET_NO_UPPERBOUND; 324 return (B_FALSE); 325 } 326 327 /* SL range must have upper bound dominating lower bound */ 328 if (!bldominates(&max_sl, &min_sl)) { 329 *errp = LTSNET_ILL_RANGE; 330 return (B_FALSE); 331 } 332 333 if (mask & RTSA_MINSL) 334 sp->rtsa_slrange.lower_bound = min_sl; 335 if (mask & RTSA_MAXSL) 336 sp->rtsa_slrange.upper_bound = max_sl; 337 if (mask & RTSA_DOI) 338 sp->rtsa_doi = doi; 339 sp->rtsa_mask = mask; 340 341 return (B_TRUE); 342 } 343 344 /* Keep in sync with libtsnet.h */ 345 static const char *tsol_errlist[] = { 346 "No error", 347 "System error", 348 "Empty string or end of list", 349 "Entry is malformed", 350 "Missing name", 351 "Missing attributes", 352 "Illegal name", 353 "Illegal keyword delimiter", 354 "Unknown keyword", 355 "Duplicate keyword", 356 "Illegal value delimiter", 357 "Missing host type", 358 "Illegal host type", 359 "Missing label", 360 "Illegal label", 361 "Missing label range", 362 "Illegal label range", 363 "No lower bound in range", 364 "Illegal lower bound in range", 365 "No upper bound in range", 366 "Illegal upper bound in range", 367 "Missing DOI", 368 "Illegal DOI", 369 "Too many entries in set", 370 "Missing address/network", 371 "Illegal address/network", 372 "Illegal flag", 373 "Illegal MLP specification", 374 "Unacceptable keyword for type" 375 }; 376 static const int tsol_nerr = sizeof (tsol_errlist) / sizeof (*tsol_errlist); 377 378 const char * 379 tsol_strerror(int libtserr, int errnoval) 380 { 381 if (libtserr == LTSNET_SYSERR) 382 return (strerror(errnoval)); 383 if (libtserr >= 0 && libtserr < tsol_nerr) 384 return (gettext(tsol_errlist[libtserr])); 385 return (gettext("Unknown error")); 386 } 387