Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 209190
b: refs/heads/master
c: 4a2d789
h: refs/heads/master
v: v3
  • Loading branch information
Wang Lei authored and Steve French committed Aug 11, 2010
1 parent 502ac6e commit dd54875
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c2e8139c9f797baa46515af6d350c51823736cbb
refs/heads/master: 4a2d789267e00b5a1175ecd2ddefcc78b83fbf09
4 changes: 4 additions & 0 deletions trunk/fs/afs/cell.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist)
if (!vllist || strlen(vllist) < 7) {
ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL);
if (ret < 0) {
if (ret == -ENODATA || ret == -EAGAIN || ret == -ENOKEY)
/* translate these errors into something
* userspace might understand */
ret = -EDESTADDRREQ;
_leave(" = %d", ret);
return ERR_PTR(ret);
}
Expand Down
92 changes: 87 additions & 5 deletions trunk/net/dns_resolver/dns_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/kernel.h>
#include <linux/keyctl.h>
#include <linux/err.h>
#include <linux/seq_file.h>
#include <keys/dns_resolver-type.h>
#include <keys/user-type.h>
#include "internal.h"
Expand All @@ -43,6 +44,8 @@ MODULE_PARM_DESC(debug, "DNS Resolver debugging mask");

const struct cred *dns_resolver_cache;

#define DNS_ERRORNO_OPTION "dnserror"

/*
* Instantiate a user defined key for dns_resolver.
*
Expand All @@ -59,9 +62,10 @@ static int
dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen)
{
struct user_key_payload *upayload;
unsigned long derrno;
int ret;
size_t result_len = 0;
const char *data = _data, *opt;
const char *data = _data, *end, *opt;

kenter("%%%d,%s,'%s',%zu",
key->serial, key->description, data, datalen);
Expand All @@ -71,13 +75,77 @@ dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen)
datalen--;

/* deal with any options embedded in the data */
end = data + datalen;
opt = memchr(data, '#', datalen);
if (!opt) {
kdebug("no options currently supported");
return -EINVAL;
/* no options: the entire data is the result */
kdebug("no options");
result_len = datalen;
} else {
const char *next_opt;

result_len = opt - data;
opt++;
kdebug("options: '%s'", opt);
do {
const char *eq;
int opt_len, opt_nlen, opt_vlen, tmp;

next_opt = memchr(opt, '#', end - opt) ?: end;
opt_len = next_opt - opt;
if (!opt_len) {
printk(KERN_WARNING
"Empty option to dns_resolver key %d\n",
key->serial);
return -EINVAL;
}

eq = memchr(opt, '=', opt_len) ?: end;
opt_nlen = eq - opt;
eq++;
opt_vlen = next_opt - eq; /* will be -1 if no value */

tmp = opt_vlen >= 0 ? opt_vlen : 0;
kdebug("option '%*.*s' val '%*.*s'",
opt_nlen, opt_nlen, opt, tmp, tmp, eq);

/* see if it's an error number representing a DNS error
* that's to be recorded as the result in this key */
if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 &&
memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) {
kdebug("dns error number option");
if (opt_vlen <= 0)
goto bad_option_value;

ret = strict_strtoul(eq, 10, &derrno);
if (ret < 0)
goto bad_option_value;

if (derrno < 1 || derrno > 511)
goto bad_option_value;

kdebug("dns error no. = %lu", derrno);
key->type_data.x[0] = -derrno;
continue;
}

bad_option_value:
printk(KERN_WARNING
"Option '%*.*s' to dns_resolver key %d:"
" bad/missing value\n",
opt_nlen, opt_nlen, opt, key->serial);
return -EINVAL;
} while (opt = next_opt + 1, opt < end);
}

/* don't cache the result if we're caching an error saying there's no
* result */
if (key->type_data.x[0]) {
kleave(" = 0 [h_error %ld]", key->type_data.x[0]);
return 0;
}

result_len = datalen;
kdebug("store result");
ret = key_payload_reserve(key, result_len);
if (ret < 0)
return -EINVAL;
Expand Down Expand Up @@ -135,13 +203,27 @@ dns_resolver_match(const struct key *key, const void *description)
return ret;
}

/*
* Describe a DNS key
*/
static void dns_resolver_describe(const struct key *key, struct seq_file *m)
{
int err = key->type_data.x[0];

seq_puts(m, key->description);
if (err)
seq_printf(m, ": %d", err);
else
seq_printf(m, ": %u", key->datalen);
}

struct key_type key_type_dns_resolver = {
.name = "dns_resolver",
.instantiate = dns_resolver_instantiate,
.match = dns_resolver_match,
.revoke = user_revoke,
.destroy = user_destroy,
.describe = user_describe,
.describe = dns_resolver_describe,
.read = user_read,
};

Expand Down
5 changes: 5 additions & 0 deletions trunk/net/dns_resolver/dns_query.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ int dns_query(const char *type, const char *name, size_t namelen,
if (ret < 0)
goto put;

/* If the DNS server gave an error, return that to the caller */
ret = rkey->type_data.x[0];
if (ret)
goto put;

upayload = rcu_dereference_protected(rkey->payload.data,
lockdep_is_held(&rkey->sem));
len = upayload->datalen;
Expand Down

0 comments on commit dd54875

Please sign in to comment.