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 1996-2003 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 <sys/types.h> 55 #include <errno.h> 56 #include "replica.h" 57 58 struct replica * 59 parse_replica(char *special, int *count) 60 { 61 struct replica *list = NULL; 62 char *root, *special2; 63 char *proot, *x, *y; 64 int scount, v6addr, i; 65 int found_colon = 0; 66 67 *count = 0; 68 scount = 0; 69 v6addr = 0; 70 root = special2 = strdup(special); 71 proot = root; 72 73 while (root) { 74 switch (*root) { 75 case '[': 76 if ((root != special2) && (*(root -1) != ',')) { 77 root++; 78 break; 79 } 80 y = strchr(root, ']'); 81 if (!y) { 82 root++; 83 break; 84 } 85 if ((*(y + 1) != ',') && (*(y + 1) != ':')) { 86 root = y + 1; 87 break; 88 } 89 /* 90 * Found a v6 Literal Address, so set "v6addr" 91 * and grab the address and store it in the list 92 * under "host part". 93 */ 94 proot = root + 1; 95 root = y + 1; 96 v6addr = 1; 97 (*count)++; 98 list = realloc(list, *count * sizeof (struct replica)); 99 if (!list) 100 goto bad; 101 *y = '\0'; 102 list[*count-1].host = strdup(proot); 103 if (!list[*count-1].host) 104 goto bad; 105 break; 106 case ':': 107 *root = '\0'; 108 x = root + 1; 109 /* 110 * Find comma (if present), which bounds the path. 111 * The comma implies that the user is trying to 112 * specify failover syntax if another colon follows. 113 */ 114 if (((y = strchr(x, ',')) != NULL) && 115 (strchr((y + 1), ':'))) { 116 root = y + 1; 117 *y = '\0'; 118 } else { 119 found_colon = 1; 120 root = NULL; 121 } 122 /* 123 * If "v6addr" is set, unset it, and since the "host 124 * part" is already taken care of, skip to the "path 125 * path" part. 126 */ 127 if (v6addr == 1) 128 v6addr = 0; 129 else { 130 (*count)++; 131 list = realloc(list, *count * 132 sizeof (struct replica)); 133 if (!list) 134 goto bad; 135 list[*count-1].host = strdup(proot); 136 if (!list[*count-1].host) 137 goto bad; 138 proot = root; 139 140 } 141 for (i = scount; i < *count; i++) { 142 list[i].path = strdup(x); 143 if (!list[i].path) 144 goto bad; 145 } 146 scount = i; 147 proot = root; 148 if (y) 149 *y = ','; 150 break; 151 case ',': 152 /* 153 * If "v6addr" is set, unset it and continue 154 * else grab the address and store it in the list 155 * under "host part". 156 */ 157 if (v6addr == 1) { 158 v6addr = 0; 159 proot = ++root; 160 } else { 161 *root = '\0'; 162 root++; 163 (*count)++; 164 list = realloc(list, *count * 165 sizeof (struct replica)); 166 if (!list) 167 goto bad; 168 list[*count-1].host = strdup(proot); 169 if (!list[*count-1].host) 170 goto bad; 171 proot = root; 172 *(root - 1) = ','; 173 } 174 break; 175 default: 176 if (*root == '\0') 177 root = NULL; 178 else 179 root++; 180 } 181 } 182 if (found_colon) { 183 free(special2); 184 return (list); 185 } 186 bad: 187 if (list) { 188 int i; 189 190 for (i = 0; i < *count; i++) { 191 if (list[i].host) 192 free(list[i].host); 193 if (list[i].path) 194 free(list[i].path); 195 } 196 free(list); 197 } 198 if (!found_colon) 199 *count = -1; 200 free(special2); 201 return (NULL); 202 } 203 204 void 205 free_replica(struct replica *list, int count) 206 { 207 int i; 208 209 for (i = 0; i < count; i++) { 210 free(list[i].host); 211 free(list[i].path); 212 } 213 free(list); 214 } 215