diff options
Diffstat (limited to 'libmailutils/sockaddr/url.c')
-rw-r--r-- | libmailutils/sockaddr/url.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/libmailutils/sockaddr/url.c b/libmailutils/sockaddr/url.c new file mode 100644 index 000000000..0eaf870be --- /dev/null +++ b/libmailutils/sockaddr/url.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2011 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU Lesser General Public | ||
6 | License as published by the Free Software Foundation; either | ||
7 | version 3 of the License, or (at your option) any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General | ||
15 | Public License along with this library. If not, see | ||
16 | <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include <sys/types.h> | ||
23 | #include <sys/socket.h> | ||
24 | #include <sys/un.h> | ||
25 | #include <sys/stat.h> | ||
26 | #include <netinet/in.h> | ||
27 | #include <arpa/inet.h> | ||
28 | #include <netdb.h> | ||
29 | #include <stdlib.h> | ||
30 | #include <errno.h> | ||
31 | #include <string.h> | ||
32 | #include <mailutils/sockaddr.h> | ||
33 | #include <mailutils/url.h> | ||
34 | #include <mailutils/io.h> | ||
35 | #include <mailutils/errno.h> | ||
36 | #include <mailutils/nls.h> | ||
37 | #include <mailutils/kwd.h> | ||
38 | |||
39 | static struct mu_kwd famtab[] = { | ||
40 | { "unix", AF_UNIX }, | ||
41 | { "local", AF_UNIX }, | ||
42 | { "inet4", AF_INET }, | ||
43 | #ifdef MAILUTILS_IPV6 | ||
44 | { "inet6", AF_INET6 }, | ||
45 | { "inet", AF_UNSPEC }, | ||
46 | #else | ||
47 | { "inet", AF_INET }, | ||
48 | #endif | ||
49 | { NULL } | ||
50 | }; | ||
51 | |||
52 | int | ||
53 | mu_sockaddr_from_url (struct mu_sockaddr **retval, mu_url_t url, | ||
54 | struct mu_sockaddr_hints *mh) | ||
55 | { | ||
56 | int rc; | ||
57 | const char *scheme; | ||
58 | const char *node = NULL, *serv = NULL; | ||
59 | struct mu_sockaddr_hints hints; | ||
60 | |||
61 | if (mh) | ||
62 | memcpy (&hints, mh, sizeof (hints)); | ||
63 | else | ||
64 | { | ||
65 | memset (&hints, sizeof(hints), 0); | ||
66 | hints.family = AF_UNSPEC; | ||
67 | hints.socktype = SOCK_STREAM; | ||
68 | hints.protocol = IPPROTO_TCP; | ||
69 | } | ||
70 | |||
71 | if (hints.family == AF_UNSPEC) | ||
72 | { | ||
73 | rc = mu_url_sget_scheme (url, &scheme); | ||
74 | if (rc) | ||
75 | return rc; | ||
76 | |||
77 | if (mu_kwd_xlat_name (famtab, scheme, &hints.family)) | ||
78 | { | ||
79 | if (hints.flags & MU_AH_DETECT_FAMILY) | ||
80 | { | ||
81 | int flags = 0; | ||
82 | |||
83 | mu_url_get_flags (url, &flags); | ||
84 | #ifdef MAILUTILS_IPV6 | ||
85 | if (flags & MU_URL_IPV6) | ||
86 | hints.family = AF_INET6; | ||
87 | else | ||
88 | #endif | ||
89 | if (flags & (MU_URL_HOST|MU_URL_PORT)) | ||
90 | hints.family = AF_INET; | ||
91 | else if (flags & MU_URL_PATH) | ||
92 | hints.family = AF_UNIX; | ||
93 | else | ||
94 | return MU_ERR_FAMILY; | ||
95 | } | ||
96 | else | ||
97 | return MU_ERR_FAMILY; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | if (hints.family == AF_UNIX) | ||
102 | { | ||
103 | rc = mu_url_sget_path (url, &node); | ||
104 | if (rc) | ||
105 | { | ||
106 | if (rc == MU_ERR_NOENT) | ||
107 | { | ||
108 | rc = mu_url_sget_host (url, &node); | ||
109 | if (rc == MU_ERR_NOENT) | ||
110 | return MU_ERR_NONAME; | ||
111 | } | ||
112 | if (rc) | ||
113 | return rc; | ||
114 | } | ||
115 | } | ||
116 | else | ||
117 | { | ||
118 | #ifdef MAILUTILS_IPV6 | ||
119 | if (hints.family == AF_UNSPEC) | ||
120 | hints.family = mu_url_has_flag (url, MU_URL_IPV6) ? AF_INET6 : AF_INET; | ||
121 | #endif | ||
122 | rc = mu_url_sget_host (url, &node); | ||
123 | if (rc && rc != MU_ERR_NOENT) | ||
124 | return MU_ERR_NONAME; | ||
125 | rc = mu_url_sget_portstr (url, &serv); | ||
126 | if (rc && rc != MU_ERR_NOENT) | ||
127 | return MU_ERR_NONAME; | ||
128 | } | ||
129 | return mu_sockaddr_from_node (retval, node, serv, &hints); | ||
130 | } | ||