1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2004-2006 Lennart Poettering 5 6 PulseAudio is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation; either version 2.1 of the 9 License, or (at your option) any later version. 10 11 PulseAudio is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <string.h> 25#include <stdlib.h> 26 27#include <pulse/xmalloc.h> 28 29#include <pulsecore/core-util.h> 30#include <pulsecore/macro.h> 31#include <pulsecore/arpa-inet.h> 32 33#include "parseaddr.h" 34 35/* Parse addresses in one of the following forms: 36 * HOSTNAME 37 * HOSTNAME:PORT 38 * [HOSTNAME] 39 * [HOSTNAME]:PORT 40 * 41 * Return a newly allocated string of the hostname and fill in *ret_port if specified */ 42 43static char *parse_host(const char *s, uint16_t *ret_port) { 44 pa_assert(s); 45 pa_assert(ret_port); 46 47 if (*s == '[') { 48 char *e; 49 if (!(e = strchr(s+1, ']'))) 50 return NULL; 51 52 if (e[1] == ':') { 53 uint32_t p; 54 55 if (pa_atou(e+2, &p) < 0) 56 return NULL; 57 58 *ret_port = (uint16_t) p; 59 } else if (e[1] != 0) 60 return NULL; 61 62 return pa_xstrndup(s+1, (size_t) (e-s-1)); 63 } else { 64 char *e; 65 uint32_t p; 66 67 if (!(e = strrchr(s, ':'))) 68 return pa_xstrdup(s); 69 70 if (pa_atou(e+1, &p) < 0) 71 return NULL; 72 73 *ret_port = (uint16_t) p; 74 return pa_xstrndup(s, (size_t) (e-s)); 75 } 76} 77 78int pa_parse_address(const char *name, pa_parsed_address *ret_p) { 79 const char *p; 80 81 pa_assert(name); 82 pa_assert(ret_p); 83 84 memset(ret_p, 0, sizeof(pa_parsed_address)); 85 ret_p->type = PA_PARSED_ADDRESS_TCP_AUTO; 86 87 if (*name == '{') { 88 char *id, *pfx; 89 90 /* The URL starts with a host id for detecting local connections */ 91 if (!(id = pa_machine_id())) 92 return -1; 93 94 pfx = pa_sprintf_malloc("{%s}", id); 95 pa_xfree(id); 96 97 if (!pa_startswith(name, pfx)) { 98 pa_xfree(pfx); 99 /* Not local */ 100 return -1; 101 } 102 103 p = name + strlen(pfx); 104 pa_xfree(pfx); 105 } else 106 p = name; 107 108#ifndef OS_IS_WIN32 109 if (*p == '/') 110 ret_p->type = PA_PARSED_ADDRESS_UNIX; 111#else 112 if (strlen(p) >= 3 && p[1] == ':' && p[2] == '\\' && ((p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z'))) 113 ret_p->type = PA_PARSED_ADDRESS_UNIX; 114#endif 115 else if (pa_startswith(p, "unix:")) { 116 ret_p->type = PA_PARSED_ADDRESS_UNIX; 117 p += sizeof("unix:")-1; 118 } else if (pa_startswith(p, "tcp:")) { 119 ret_p->type = PA_PARSED_ADDRESS_TCP4; 120 p += sizeof("tcp:")-1; 121 } else if (pa_startswith(p, "tcp4:")) { 122 ret_p->type = PA_PARSED_ADDRESS_TCP4; 123 p += sizeof("tcp4:")-1; 124 } else if (pa_startswith(p, "tcp6:")) { 125 ret_p->type = PA_PARSED_ADDRESS_TCP6; 126 p += sizeof("tcp6:")-1; 127 } 128 129 if (ret_p->type == PA_PARSED_ADDRESS_UNIX) 130 ret_p->path_or_host = pa_xstrdup(p); 131 else 132 if (!(ret_p->path_or_host = parse_host(p, &ret_p->port))) 133 return -1; 134 135 return 0; 136} 137 138bool pa_is_ip_address(const char *a) { 139 char buf[INET6_ADDRSTRLEN]; 140 141 pa_assert(a); 142 143 if (inet_pton(AF_INET6, a, buf) >= 1) 144 return true; 145 146 if (inet_pton(AF_INET, a, buf) >= 1) 147 return true; 148 149 return false; 150} 151 152bool pa_is_ip6_address(const char *a) { 153 char buf[INET6_ADDRSTRLEN]; 154 155 pa_assert(a); 156 157 if (inet_pton(AF_INET6, a, buf) >= 1) 158 return true; 159 160 return false; 161} 162