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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * replica.c 24 * 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 /* 30 * Parse replicated server lists of the form: 31 * 32 * host1:/path1,host2,host3,host4:/path2,host5:/path3 33 * 34 * into an array containing its constituent parts: 35 * 36 * host1 /path1 37 * host2 /path2 38 * host3 /path2 39 * host4 /path2 40 * host5 /path3 41 * where a server could also be represented in form of literal address 42 * and in case it is an IPv6 literal address it will be enclosed in 43 * square brackets [IPv6 Literal address] 44 * Problems indicated by null return; they will be memory allocation 45 * errors worthy of an error message unless count == -1, which means 46 * a parse error. 47 */ 48 49 #pragma ident "%Z%%M% %I% %E% SMI" 50 51 #include <stdio.h> 52 #include <malloc.h> 53 #include <string.h> 54 #include <strings.h> 55 #include <sys/types.h> 56 #include <errno.h> 57 #include "replica.h" 58 59 void 60 free_replica(struct replica *list, int count) 61 { 62 int i; 63 64 for (i = 0; i < count; i++) { 65 if (list[i].host) 66 free(list[i].host); 67 if (list[i].path) 68 free(list[i].path); 69 } 70 free(list); 71 } 72 73 struct replica * 74 parse_replica(char *special, int *count) 75 { 76 struct replica *list = NULL; 77 char *root, *special2; 78 char *proot, *x, *y; 79 int scount, v6addr, i; 80 int found_colon = 0; 81 82 *count = 0; 83 scount = 0; 84 v6addr = 0; 85 root = special2 = strdup(special); 86 proot = root; 87 88 while (root) { 89 switch (*root) { 90 case '[': 91 if ((root != special2) && (*(root -1) != ',')) { 92 root++; 93 break; 94 } 95 y = strchr(root, ']'); 96 if (!y) { 97 root++; 98 break; 99 } 100 if ((*(y + 1) != ',') && (*(y + 1) != ':')) { 101 root = y + 1; 102 break; 103 } 104 /* 105 * Found a v6 Literal Address, so set "v6addr" 106 * and grab the address and store it in the list 107 * under "host part". 108 */ 109 proot = root + 1; 110 root = y + 1; 111 v6addr = 1; 112 if ((list = realloc(list, (*count + 1) * 113 sizeof (struct replica))) == NULL) 114 goto bad; 115 bzero(&list[(*count)++], sizeof (struct replica)); 116 *y = '\0'; 117 list[*count-1].host = strdup(proot); 118 if (!list[*count-1].host) 119 goto bad; 120 break; 121 case ':': 122 *root = '\0'; 123 x = root + 1; 124 /* 125 * Find comma (if present), which bounds the path. 126 * The comma implies that the user is trying to 127 * specify failover syntax if another colon follows. 128 */ 129 if (((y = strchr(x, ',')) != NULL) && 130 (strchr((y + 1), ':'))) { 131 root = y + 1; 132 *y = '\0'; 133 } else { 134 found_colon = 1; 135 root = NULL; 136 } 137 /* 138 * If "v6addr" is set, unset it, and since the "host 139 * part" is already taken care of, skip to the "path 140 * path" part. 141 */ 142 if (v6addr == 1) 143 v6addr = 0; 144 else { 145 if ((list = realloc(list, (*count + 1) * 146 sizeof (struct replica))) == NULL) 147 goto bad; 148 bzero(&list[(*count)++], 149 sizeof (struct replica)); 150 list[*count-1].host = strdup(proot); 151 if (!list[*count-1].host) 152 goto bad; 153 proot = root; 154 155 } 156 for (i = scount; i < *count; i++) { 157 list[i].path = strdup(x); 158 if (!list[i].path) 159 goto bad; 160 } 161 scount = i; 162 proot = root; 163 if (y) 164 *y = ','; 165 break; 166 case ',': 167 /* 168 * If "v6addr" is set, unset it and continue 169 * else grab the address and store it in the list 170 * under "host part". 171 */ 172 if (v6addr == 1) { 173 v6addr = 0; 174 proot = ++root; 175 } else { 176 *root = '\0'; 177 root++; 178 if ((list = realloc(list, (*count + 1) * 179 sizeof (struct replica))) == NULL) 180 goto bad; 181 bzero(&list[(*count)++], 182 sizeof (struct replica)); 183 list[*count-1].host = strdup(proot); 184 if (!list[*count-1].host) 185 goto bad; 186 proot = root; 187 *(root - 1) = ','; 188 } 189 break; 190 default: 191 if (*root == '\0') 192 root = NULL; 193 else 194 root++; 195 } 196 } 197 if (found_colon) { 198 free(special2); 199 return (list); 200 } 201 bad: 202 if (list) 203 free_replica(list, *count); 204 if (!found_colon) 205 *count = -1; 206 free(special2); 207 return (NULL); 208 } 209