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