17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * replica.c 247c478bd9Sstevel@tonic-gate * 25*c72ac7bbSfrankho * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 267c478bd9Sstevel@tonic-gate * Use is subject to license terms. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Parse replicated server lists of the form: 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * host1:/path1,host2,host3,host4:/path2,host5:/path3 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate * into an array containing its constituent parts: 357c478bd9Sstevel@tonic-gate * 367c478bd9Sstevel@tonic-gate * host1 /path1 377c478bd9Sstevel@tonic-gate * host2 /path2 387c478bd9Sstevel@tonic-gate * host3 /path2 397c478bd9Sstevel@tonic-gate * host4 /path2 407c478bd9Sstevel@tonic-gate * host5 /path3 417c478bd9Sstevel@tonic-gate * where a server could also be represented in form of literal address 427c478bd9Sstevel@tonic-gate * and in case it is an IPv6 literal address it will be enclosed in 437c478bd9Sstevel@tonic-gate * square brackets [IPv6 Literal address] 447c478bd9Sstevel@tonic-gate * Problems indicated by null return; they will be memory allocation 457c478bd9Sstevel@tonic-gate * errors worthy of an error message unless count == -1, which means 467c478bd9Sstevel@tonic-gate * a parse error. 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #include <stdio.h> 527c478bd9Sstevel@tonic-gate #include <malloc.h> 537c478bd9Sstevel@tonic-gate #include <string.h> 54*c72ac7bbSfrankho #include <strings.h> 557c478bd9Sstevel@tonic-gate #include <sys/types.h> 567c478bd9Sstevel@tonic-gate #include <errno.h> 577c478bd9Sstevel@tonic-gate #include "replica.h" 587c478bd9Sstevel@tonic-gate 59*c72ac7bbSfrankho void 60*c72ac7bbSfrankho free_replica(struct replica *list, int count) 61*c72ac7bbSfrankho { 62*c72ac7bbSfrankho int i; 63*c72ac7bbSfrankho 64*c72ac7bbSfrankho for (i = 0; i < count; i++) { 65*c72ac7bbSfrankho if (list[i].host) 66*c72ac7bbSfrankho free(list[i].host); 67*c72ac7bbSfrankho if (list[i].path) 68*c72ac7bbSfrankho free(list[i].path); 69*c72ac7bbSfrankho } 70*c72ac7bbSfrankho free(list); 71*c72ac7bbSfrankho } 72*c72ac7bbSfrankho 737c478bd9Sstevel@tonic-gate struct replica * 747c478bd9Sstevel@tonic-gate parse_replica(char *special, int *count) 757c478bd9Sstevel@tonic-gate { 767c478bd9Sstevel@tonic-gate struct replica *list = NULL; 777c478bd9Sstevel@tonic-gate char *root, *special2; 787c478bd9Sstevel@tonic-gate char *proot, *x, *y; 797c478bd9Sstevel@tonic-gate int scount, v6addr, i; 807c478bd9Sstevel@tonic-gate int found_colon = 0; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate *count = 0; 837c478bd9Sstevel@tonic-gate scount = 0; 847c478bd9Sstevel@tonic-gate v6addr = 0; 857c478bd9Sstevel@tonic-gate root = special2 = strdup(special); 867c478bd9Sstevel@tonic-gate proot = root; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate while (root) { 897c478bd9Sstevel@tonic-gate switch (*root) { 907c478bd9Sstevel@tonic-gate case '[': 917c478bd9Sstevel@tonic-gate if ((root != special2) && (*(root -1) != ',')) { 927c478bd9Sstevel@tonic-gate root++; 937c478bd9Sstevel@tonic-gate break; 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate y = strchr(root, ']'); 967c478bd9Sstevel@tonic-gate if (!y) { 977c478bd9Sstevel@tonic-gate root++; 987c478bd9Sstevel@tonic-gate break; 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate if ((*(y + 1) != ',') && (*(y + 1) != ':')) { 1017c478bd9Sstevel@tonic-gate root = y + 1; 1027c478bd9Sstevel@tonic-gate break; 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * Found a v6 Literal Address, so set "v6addr" 1067c478bd9Sstevel@tonic-gate * and grab the address and store it in the list 1077c478bd9Sstevel@tonic-gate * under "host part". 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate proot = root + 1; 1107c478bd9Sstevel@tonic-gate root = y + 1; 1117c478bd9Sstevel@tonic-gate v6addr = 1; 112*c72ac7bbSfrankho if ((list = realloc(list, (*count + 1) * 113*c72ac7bbSfrankho sizeof (struct replica))) == NULL) 1147c478bd9Sstevel@tonic-gate goto bad; 115*c72ac7bbSfrankho bzero(&list[(*count)++], sizeof (struct replica)); 1167c478bd9Sstevel@tonic-gate *y = '\0'; 1177c478bd9Sstevel@tonic-gate list[*count-1].host = strdup(proot); 1187c478bd9Sstevel@tonic-gate if (!list[*count-1].host) 1197c478bd9Sstevel@tonic-gate goto bad; 1207c478bd9Sstevel@tonic-gate break; 1217c478bd9Sstevel@tonic-gate case ':': 1227c478bd9Sstevel@tonic-gate *root = '\0'; 1237c478bd9Sstevel@tonic-gate x = root + 1; 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * Find comma (if present), which bounds the path. 1267c478bd9Sstevel@tonic-gate * The comma implies that the user is trying to 1277c478bd9Sstevel@tonic-gate * specify failover syntax if another colon follows. 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate if (((y = strchr(x, ',')) != NULL) && 1307c478bd9Sstevel@tonic-gate (strchr((y + 1), ':'))) { 1317c478bd9Sstevel@tonic-gate root = y + 1; 1327c478bd9Sstevel@tonic-gate *y = '\0'; 1337c478bd9Sstevel@tonic-gate } else { 1347c478bd9Sstevel@tonic-gate found_colon = 1; 1357c478bd9Sstevel@tonic-gate root = NULL; 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * If "v6addr" is set, unset it, and since the "host 1397c478bd9Sstevel@tonic-gate * part" is already taken care of, skip to the "path 1407c478bd9Sstevel@tonic-gate * path" part. 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate if (v6addr == 1) 1437c478bd9Sstevel@tonic-gate v6addr = 0; 1447c478bd9Sstevel@tonic-gate else { 145*c72ac7bbSfrankho if ((list = realloc(list, (*count + 1) * 146*c72ac7bbSfrankho sizeof (struct replica))) == NULL) 1477c478bd9Sstevel@tonic-gate goto bad; 148*c72ac7bbSfrankho bzero(&list[(*count)++], 149*c72ac7bbSfrankho sizeof (struct replica)); 1507c478bd9Sstevel@tonic-gate list[*count-1].host = strdup(proot); 1517c478bd9Sstevel@tonic-gate if (!list[*count-1].host) 1527c478bd9Sstevel@tonic-gate goto bad; 1537c478bd9Sstevel@tonic-gate proot = root; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate for (i = scount; i < *count; i++) { 1577c478bd9Sstevel@tonic-gate list[i].path = strdup(x); 1587c478bd9Sstevel@tonic-gate if (!list[i].path) 1597c478bd9Sstevel@tonic-gate goto bad; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate scount = i; 1627c478bd9Sstevel@tonic-gate proot = root; 1637c478bd9Sstevel@tonic-gate if (y) 1647c478bd9Sstevel@tonic-gate *y = ','; 1657c478bd9Sstevel@tonic-gate break; 1667c478bd9Sstevel@tonic-gate case ',': 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * If "v6addr" is set, unset it and continue 1697c478bd9Sstevel@tonic-gate * else grab the address and store it in the list 1707c478bd9Sstevel@tonic-gate * under "host part". 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate if (v6addr == 1) { 1737c478bd9Sstevel@tonic-gate v6addr = 0; 1747c478bd9Sstevel@tonic-gate proot = ++root; 1757c478bd9Sstevel@tonic-gate } else { 1767c478bd9Sstevel@tonic-gate *root = '\0'; 1777c478bd9Sstevel@tonic-gate root++; 178*c72ac7bbSfrankho if ((list = realloc(list, (*count + 1) * 179*c72ac7bbSfrankho sizeof (struct replica))) == NULL) 1807c478bd9Sstevel@tonic-gate goto bad; 181*c72ac7bbSfrankho bzero(&list[(*count)++], 182*c72ac7bbSfrankho sizeof (struct replica)); 1837c478bd9Sstevel@tonic-gate list[*count-1].host = strdup(proot); 1847c478bd9Sstevel@tonic-gate if (!list[*count-1].host) 1857c478bd9Sstevel@tonic-gate goto bad; 1867c478bd9Sstevel@tonic-gate proot = root; 1877c478bd9Sstevel@tonic-gate *(root - 1) = ','; 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate break; 1907c478bd9Sstevel@tonic-gate default: 1917c478bd9Sstevel@tonic-gate if (*root == '\0') 1927c478bd9Sstevel@tonic-gate root = NULL; 1937c478bd9Sstevel@tonic-gate else 1947c478bd9Sstevel@tonic-gate root++; 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate if (found_colon) { 1987c478bd9Sstevel@tonic-gate free(special2); 1997c478bd9Sstevel@tonic-gate return (list); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate bad: 202*c72ac7bbSfrankho if (list) 203*c72ac7bbSfrankho free_replica(list, *count); 2047c478bd9Sstevel@tonic-gate if (!found_colon) 2057c478bd9Sstevel@tonic-gate *count = -1; 2067c478bd9Sstevel@tonic-gate free(special2); 2077c478bd9Sstevel@tonic-gate return (NULL); 2087c478bd9Sstevel@tonic-gate } 209