aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-07 15:54:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-07 15:54:46 -0400
commit1fc7995d19139d6f99203b43c161968f3f554a15 (patch)
tree8ad219a60e85935df878f2f9927a58b84f63433e /net
parent3b7433b8a8a83c87972065b1852b7dcae691e464 (diff)
parent5227bbb008fa6d2efddd86170bdfac2020cf571d (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: [DNS RESOLVER] Minor typo correction DNS: Fixes for the DNS query module cifs: Include linux/err.h for IS_ERR and PTR_ERR DNS: Make AFS go to the DNS for AFSDB records for unknown cells DNS: Separate out CIFS DNS Resolver code cifs: account for new creduid=0x%x parameter in spnego upcall string cifs: reduce false positives with inode aliasing serverino autodisable CIFS: Make cifs_convert_address() take a const src pointer and a length cifs: show features compiled in as part of DebugData cifs: update README Fix up trivial conflicts in fs/cifs/cifsfs.c due to workqueue changes
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/dns_resolver/Kconfig27
-rw-r--r--net/dns_resolver/Makefile7
-rw-r--r--net/dns_resolver/dns_key.c211
-rw-r--r--net/dns_resolver/dns_query.c160
-rw-r--r--net/dns_resolver/internal.h44
7 files changed, 451 insertions, 0 deletions
diff --git a/net/Kconfig b/net/Kconfig
index e24fa0873f32..e330594d3709 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -213,6 +213,7 @@ source "net/phonet/Kconfig"
213source "net/ieee802154/Kconfig" 213source "net/ieee802154/Kconfig"
214source "net/sched/Kconfig" 214source "net/sched/Kconfig"
215source "net/dcb/Kconfig" 215source "net/dcb/Kconfig"
216source "net/dns_resolver/Kconfig"
216 217
217config RPS 218config RPS
218 boolean 219 boolean
diff --git a/net/Makefile b/net/Makefile
index 41d420070a38..ea60fbce9b1b 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -67,3 +67,4 @@ ifeq ($(CONFIG_NET),y)
67obj-$(CONFIG_SYSCTL) += sysctl_net.o 67obj-$(CONFIG_SYSCTL) += sysctl_net.o
68endif 68endif
69obj-$(CONFIG_WIMAX) += wimax/ 69obj-$(CONFIG_WIMAX) += wimax/
70obj-$(CONFIG_DNS_RESOLVER) += dns_resolver/
diff --git a/net/dns_resolver/Kconfig b/net/dns_resolver/Kconfig
new file mode 100644
index 000000000000..50d49f7e0472
--- /dev/null
+++ b/net/dns_resolver/Kconfig
@@ -0,0 +1,27 @@
1#
2# Configuration for DNS Resolver
3#
4config DNS_RESOLVER
5 tristate "DNS Resolver support"
6 depends on NET && KEYS
7 help
8 Saying Y here will include support for the DNS Resolver key type
9 which can be used to make upcalls to perform DNS lookups in
10 userspace.
11
12 DNS Resolver is used to query DNS server for information. Examples
13 being resolving a UNC hostname element to an IP address for CIFS or
14 performing a DNS query for AFSDB records so that AFS can locate a
15 cell's volume location database servers.
16
17 DNS Resolver is used by the CIFS and AFS modules, and would support
18 SMB2 later. DNS Resolver is supported by the userspace upcall
19 helper "/sbin/dns.resolver" via /etc/request-key.conf.
20
21 See <file:Documentation/networking/dns_resolver.txt> for further
22 information.
23
24 To compile this as a module, choose M here: the module will be called
25 dnsresolver.
26
27 If unsure, say N.
diff --git a/net/dns_resolver/Makefile b/net/dns_resolver/Makefile
new file mode 100644
index 000000000000..c0ef4e71dc49
--- /dev/null
+++ b/net/dns_resolver/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the Linux DNS Resolver.
3#
4
5obj-$(CONFIG_DNS_RESOLVER) += dns_resolver.o
6
7dns_resolver-objs := dns_key.o dns_query.o
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
new file mode 100644
index 000000000000..400a04d5c9a1
--- /dev/null
+++ b/net/dns_resolver/dns_key.c
@@ -0,0 +1,211 @@
1/* Key type used to cache DNS lookups made by the kernel
2 *
3 * See Documentation/networking/dns_resolver.txt
4 *
5 * Copyright (c) 2007 Igor Mammedov
6 * Author(s): Igor Mammedov (niallain@gmail.com)
7 * Steve French (sfrench@us.ibm.com)
8 * Wang Lei (wang840925@gmail.com)
9 * David Howells (dhowells@redhat.com)
10 *
11 * This library is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published
13 * by the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/slab.h>
28#include <linux/string.h>
29#include <linux/kernel.h>
30#include <linux/keyctl.h>
31#include <linux/err.h>
32#include <keys/dns_resolver-type.h>
33#include <keys/user-type.h>
34#include "internal.h"
35
36MODULE_DESCRIPTION("DNS Resolver");
37MODULE_AUTHOR("Wang Lei");
38MODULE_LICENSE("GPL");
39
40unsigned dns_resolver_debug;
41module_param_named(debug, dns_resolver_debug, uint, S_IWUSR | S_IRUGO);
42MODULE_PARM_DESC(debug, "DNS Resolver debugging mask");
43
44const struct cred *dns_resolver_cache;
45
46/*
47 * Instantiate a user defined key for dns_resolver.
48 *
49 * The data must be a NUL-terminated string, with the NUL char accounted in
50 * datalen.
51 *
52 * If the data contains a '#' characters, then we take the clause after each
53 * one to be an option of the form 'key=value'. The actual data of interest is
54 * the string leading up to the first '#'. For instance:
55 *
56 * "ip1,ip2,...#foo=bar"
57 */
58static int
59dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen)
60{
61 struct user_key_payload *upayload;
62 int ret;
63 size_t result_len = 0;
64 const char *data = _data, *opt;
65
66 kenter("%%%d,%s,'%s',%zu",
67 key->serial, key->description, data, datalen);
68
69 if (datalen <= 1 || !data || data[datalen - 1] != '\0')
70 return -EINVAL;
71 datalen--;
72
73 /* deal with any options embedded in the data */
74 opt = memchr(data, '#', datalen);
75 if (!opt) {
76 kdebug("no options currently supported");
77 return -EINVAL;
78 }
79
80 result_len = datalen;
81 ret = key_payload_reserve(key, result_len);
82 if (ret < 0)
83 return -EINVAL;
84
85 upayload = kmalloc(sizeof(*upayload) + result_len + 1, GFP_KERNEL);
86 if (!upayload) {
87 kleave(" = -ENOMEM");
88 return -ENOMEM;
89 }
90
91 upayload->datalen = result_len;
92 memcpy(upayload->data, data, result_len);
93 upayload->data[result_len] = '\0';
94 rcu_assign_pointer(key->payload.data, upayload);
95
96 kleave(" = 0");
97 return 0;
98}
99
100/*
101 * The description is of the form "[<type>:]<domain_name>"
102 *
103 * The domain name may be a simple name or an absolute domain name (which
104 * should end with a period). The domain name is case-independent.
105 */
106static int
107dns_resolver_match(const struct key *key, const void *description)
108{
109 int slen, dlen, ret = 0;
110 const char *src = key->description, *dsp = description;
111
112 kenter("%s,%s", src, dsp);
113
114 if (!src || !dsp)
115 goto no_match;
116
117 if (strcasecmp(src, dsp) == 0)
118 goto matched;
119
120 slen = strlen(src);
121 dlen = strlen(dsp);
122 if (slen <= 0 || dlen <= 0)
123 goto no_match;
124 if (src[slen - 1] == '.')
125 slen--;
126 if (dsp[dlen - 1] == '.')
127 dlen--;
128 if (slen != dlen || strncasecmp(src, dsp, slen) != 0)
129 goto no_match;
130
131matched:
132 ret = 1;
133no_match:
134 kleave(" = %d", ret);
135 return ret;
136}
137
138struct key_type key_type_dns_resolver = {
139 .name = "dns_resolver",
140 .instantiate = dns_resolver_instantiate,
141 .match = dns_resolver_match,
142 .revoke = user_revoke,
143 .destroy = user_destroy,
144 .describe = user_describe,
145 .read = user_read,
146};
147
148static int __init init_dns_resolver(void)
149{
150 struct cred *cred;
151 struct key *keyring;
152 int ret;
153
154 printk(KERN_NOTICE "Registering the %s key type\n",
155 key_type_dns_resolver.name);
156
157 /* create an override credential set with a special thread keyring in
158 * which DNS requests are cached
159 *
160 * this is used to prevent malicious redirections from being installed
161 * with add_key().
162 */
163 cred = prepare_kernel_cred(NULL);
164 if (!cred)
165 return -ENOMEM;
166
167 keyring = key_alloc(&key_type_keyring, ".dns_resolver", 0, 0, cred,
168 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
169 KEY_USR_VIEW | KEY_USR_READ,
170 KEY_ALLOC_NOT_IN_QUOTA);
171 if (IS_ERR(keyring)) {
172 ret = PTR_ERR(keyring);
173 goto failed_put_cred;
174 }
175
176 ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
177 if (ret < 0)
178 goto failed_put_key;
179
180 ret = register_key_type(&key_type_dns_resolver);
181 if (ret < 0)
182 goto failed_put_key;
183
184 /* instruct request_key() to use this special keyring as a cache for
185 * the results it looks up */
186 cred->thread_keyring = keyring;
187 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
188 dns_resolver_cache = cred;
189
190 kdebug("DNS resolver keyring: %d\n", key_serial(keyring));
191 return 0;
192
193failed_put_key:
194 key_put(keyring);
195failed_put_cred:
196 put_cred(cred);
197 return ret;
198}
199
200static void __exit exit_dns_resolver(void)
201{
202 key_revoke(dns_resolver_cache->thread_keyring);
203 unregister_key_type(&key_type_dns_resolver);
204 put_cred(dns_resolver_cache);
205 printk(KERN_NOTICE "Unregistered %s key type\n",
206 key_type_dns_resolver.name);
207}
208
209module_init(init_dns_resolver)
210module_exit(exit_dns_resolver)
211MODULE_LICENSE("GPL");
diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c
new file mode 100644
index 000000000000..03d5255f5cf2
--- /dev/null
+++ b/net/dns_resolver/dns_query.c
@@ -0,0 +1,160 @@
1/* Upcall routine, designed to work as a key type and working through
2 * /sbin/request-key to contact userspace when handling DNS queries.
3 *
4 * See Documentation/networking/dns_resolver.txt
5 *
6 * Copyright (c) 2007 Igor Mammedov
7 * Author(s): Igor Mammedov (niallain@gmail.com)
8 * Steve French (sfrench@us.ibm.com)
9 * Wang Lei (wang840925@gmail.com)
10 * David Howells (dhowells@redhat.com)
11 *
12 * The upcall wrapper used to make an arbitrary DNS query.
13 *
14 * This function requires the appropriate userspace tool dns.upcall to be
15 * installed and something like the following lines should be added to the
16 * /etc/request-key.conf file:
17 *
18 * create dns_resolver * * /sbin/dns.upcall %k
19 *
20 * For example to use this module to query AFSDB RR:
21 *
22 * create dns_resolver afsdb:* * /sbin/dns.afsdb %k
23 *
24 * This library is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU Lesser General Public License as published
26 * by the Free Software Foundation; either version 2.1 of the License, or
27 * (at your option) any later version.
28 *
29 * This library is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
32 * the GNU Lesser General Public License for more details.
33 *
34 * You should have received a copy of the GNU Lesser General Public License
35 * along with this library; if not, write to the Free Software
36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 */
38
39#include <linux/module.h>
40#include <linux/slab.h>
41#include <linux/dns_resolver.h>
42#include <linux/err.h>
43#include <keys/dns_resolver-type.h>
44#include <keys/user-type.h>
45
46#include "internal.h"
47
48/**
49 * dns_query - Query the DNS
50 * @type: Query type (or NULL for straight host->IP lookup)
51 * @name: Name to look up
52 * @namelen: Length of name
53 * @options: Request options (or NULL if no options)
54 * @_result: Where to place the returned data.
55 * @_expiry: Where to store the result expiry time (or NULL)
56 *
57 * The data will be returned in the pointer at *result, and the caller is
58 * responsible for freeing it.
59 *
60 * The description should be of the form "[<query_type>:]<domain_name>", and
61 * the options need to be appropriate for the query type requested. If no
62 * query_type is given, then the query is a straight hostname to IP address
63 * lookup.
64 *
65 * The DNS resolution lookup is performed by upcalling to userspace by way of
66 * requesting a key of type dns_resolver.
67 *
68 * Returns the size of the result on success, -ve error code otherwise.
69 */
70int dns_query(const char *type, const char *name, size_t namelen,
71 const char *options, char **_result, time_t *_expiry)
72{
73 struct key *rkey;
74 struct user_key_payload *upayload;
75 const struct cred *saved_cred;
76 size_t typelen, desclen;
77 char *desc, *cp;
78 int ret, len;
79
80 kenter("%s,%*.*s,%zu,%s",
81 type, (int)namelen, (int)namelen, name, namelen, options);
82
83 if (!name || namelen == 0 || !_result)
84 return -EINVAL;
85
86 /* construct the query key description as "[<type>:]<name>" */
87 typelen = 0;
88 desclen = 0;
89 if (type) {
90 typelen = strlen(type);
91 if (typelen < 1)
92 return -EINVAL;
93 desclen += typelen + 1;
94 }
95
96 if (!namelen)
97 namelen = strlen(name);
98 if (namelen < 3)
99 return -EINVAL;
100 desclen += namelen + 1;
101
102 desc = kmalloc(desclen, GFP_KERNEL);
103 if (!desc)
104 return -ENOMEM;
105
106 cp = desc;
107 if (type) {
108 memcpy(cp, type, typelen);
109 cp += typelen;
110 *cp++ = ':';
111 }
112 memcpy(cp, name, namelen);
113 cp += namelen;
114 *cp = '\0';
115
116 if (!options)
117 options = "";
118 kdebug("call request_key(,%s,%s)", desc, options);
119
120 /* make the upcall, using special credentials to prevent the use of
121 * add_key() to preinstall malicious redirections
122 */
123 saved_cred = override_creds(dns_resolver_cache);
124 rkey = request_key(&key_type_dns_resolver, desc, options);
125 revert_creds(saved_cred);
126 kfree(desc);
127 if (IS_ERR(rkey)) {
128 ret = PTR_ERR(rkey);
129 goto out;
130 }
131
132 down_read(&rkey->sem);
133 rkey->perm |= KEY_USR_VIEW;
134
135 ret = key_validate(rkey);
136 if (ret < 0)
137 goto put;
138
139 upayload = rcu_dereference_protected(rkey->payload.data,
140 lockdep_is_held(&rkey->sem));
141 len = upayload->datalen;
142
143 ret = -ENOMEM;
144 *_result = kmalloc(len + 1, GFP_KERNEL);
145 if (!*_result)
146 goto put;
147
148 memcpy(*_result, upayload->data, len + 1);
149 if (_expiry)
150 *_expiry = rkey->expiry;
151
152 ret = len;
153put:
154 up_read(&rkey->sem);
155 key_put(rkey);
156out:
157 kleave(" = %d", ret);
158 return ret;
159}
160EXPORT_SYMBOL(dns_query);
diff --git a/net/dns_resolver/internal.h b/net/dns_resolver/internal.h
new file mode 100644
index 000000000000..189ca9e9b785
--- /dev/null
+++ b/net/dns_resolver/internal.h
@@ -0,0 +1,44 @@
1/*
2 * Copyright (c) 2010 Wang Lei
3 * Author(s): Wang Lei (wang840925@gmail.com). All Rights Reserved.
4 *
5 * Internal DNS Rsolver stuff
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/compiler.h>
23#include <linux/kernel.h>
24#include <linux/sched.h>
25
26/*
27 * dns_key.c
28 */
29extern const struct cred *dns_resolver_cache;
30
31/*
32 * debug tracing
33 */
34extern unsigned dns_resolver_debug;
35
36#define kdebug(FMT, ...) \
37do { \
38 if (unlikely(dns_resolver_debug)) \
39 printk(KERN_DEBUG "[%-6.6s] "FMT"\n", \
40 current->comm, ##__VA_ARGS__); \
41} while (0)
42
43#define kenter(FMT, ...) kdebug("==> %s("FMT")", __func__, ##__VA_ARGS__)
44#define kleave(FMT, ...) kdebug("<== %s()"FMT"", __func__, ##__VA_ARGS__)