diff options
-rw-r--r-- | drivers/net/ethernet/cavium/liquidio/lio_core.c | 4 | ||||
-rw-r--r-- | drivers/net/ieee802154/mac802154_hwsim.c | 8 | ||||
-rw-r--r-- | drivers/net/ieee802154/mcr20a.c | 64 | ||||
-rw-r--r-- | include/linux/dns_resolver.h | 4 | ||||
-rw-r--r-- | include/uapi/linux/dns_resolver.h | 116 | ||||
-rw-r--r-- | net/dns_resolver/dns_key.c | 67 | ||||
-rw-r--r-- | net/dns_resolver/dns_query.c | 5 |
7 files changed, 197 insertions, 71 deletions
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c index eb96b0613cf6..825a28e5b544 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_core.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c @@ -1732,7 +1732,7 @@ int liquidio_set_fec(struct lio *lio, int on_off) if (oct->props[lio->ifidx].fec != oct->props[lio->ifidx].fec_boot) { dev_dbg(&oct->pci_dev->dev, - "Reloade driver to chang fec to %s\n", + "Reload driver to change fec to %s\n", oct->props[lio->ifidx].fec ? "on" : "off"); } @@ -1796,7 +1796,7 @@ int liquidio_get_fec(struct lio *lio) if (oct->props[lio->ifidx].fec != oct->props[lio->ifidx].fec_boot) { dev_dbg(&oct->pci_dev->dev, - "Reloade driver to chang fec to %s\n", + "Reload driver to change fec to %s\n", oct->props[lio->ifidx].fec ? "on" : "off"); } diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c index bf70ab892e69..51b5198d5943 100644 --- a/drivers/net/ieee802154/mac802154_hwsim.c +++ b/drivers/net/ieee802154/mac802154_hwsim.c @@ -37,8 +37,6 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(hwsim_phys); static DEFINE_MUTEX(hwsim_phys_lock); -static LIST_HEAD(hwsim_ifup_phys); - static struct platform_device *mac802154hwsim_dev; /* MAC802154_HWSIM netlink family */ @@ -85,7 +83,6 @@ struct hwsim_phy { struct list_head edges; struct list_head list; - struct list_head list_ifup; }; static int hwsim_add_one(struct genl_info *info, struct device *dev, @@ -159,9 +156,6 @@ static int hwsim_hw_start(struct ieee802154_hw *hw) struct hwsim_phy *phy = hw->priv; phy->suspended = false; - list_add_rcu(&phy->list_ifup, &hwsim_ifup_phys); - synchronize_rcu(); - return 0; } @@ -170,8 +164,6 @@ static void hwsim_hw_stop(struct ieee802154_hw *hw) struct hwsim_phy *phy = hw->priv; phy->suspended = true; - list_del_rcu(&phy->list_ifup); - synchronize_rcu(); } static int diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c index 04891429a554..44de81e5f140 100644 --- a/drivers/net/ieee802154/mcr20a.c +++ b/drivers/net/ieee802154/mcr20a.c @@ -132,11 +132,6 @@ static const struct reg_sequence mar20a_iar_overwrites[] = { }; #define MCR20A_VALID_CHANNELS (0x07FFF800) - -struct mcr20a_platform_data { - int rst_gpio; -}; - #define MCR20A_MAX_BUF (127) #define printdev(X) (&X->spi->dev) @@ -412,7 +407,6 @@ struct mcr20a_local { struct spi_device *spi; struct ieee802154_hw *hw; - struct mcr20a_platform_data *pdata; struct regmap *regmap_dar; struct regmap *regmap_iar; @@ -976,20 +970,6 @@ static irqreturn_t mcr20a_irq_isr(int irq, void *data) return IRQ_HANDLED; } -static int mcr20a_get_platform_data(struct spi_device *spi, - struct mcr20a_platform_data *pdata) -{ - int ret = 0; - - if (!spi->dev.of_node) - return -EINVAL; - - pdata->rst_gpio = of_get_named_gpio(spi->dev.of_node, "rst_b-gpio", 0); - dev_dbg(&spi->dev, "rst_b-gpio: %d\n", pdata->rst_gpio); - - return ret; -} - static void mcr20a_hw_setup(struct mcr20a_local *lp) { u8 i; @@ -1249,7 +1229,7 @@ mcr20a_probe(struct spi_device *spi) { struct ieee802154_hw *hw; struct mcr20a_local *lp; - struct mcr20a_platform_data *pdata; + struct gpio_desc *rst_b; int irq_type; int ret = -ENOMEM; @@ -1260,48 +1240,32 @@ mcr20a_probe(struct spi_device *spi) return -EINVAL; } - pdata = kmalloc(sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - /* set mcr20a platform data */ - ret = mcr20a_get_platform_data(spi, pdata); - if (ret < 0) { - dev_crit(&spi->dev, "mcr20a_get_platform_data failed.\n"); - goto free_pdata; - } - - /* init reset gpio */ - if (gpio_is_valid(pdata->rst_gpio)) { - ret = devm_gpio_request_one(&spi->dev, pdata->rst_gpio, - GPIOF_OUT_INIT_HIGH, "reset"); - if (ret) - goto free_pdata; + rst_b = devm_gpiod_get(&spi->dev, "rst_b", GPIOD_OUT_HIGH); + if (IS_ERR(rst_b)) { + ret = PTR_ERR(rst_b); + if (ret != -EPROBE_DEFER) + dev_err(&spi->dev, "Failed to get 'rst_b' gpio: %d", ret); + return ret; } /* reset mcr20a */ - if (gpio_is_valid(pdata->rst_gpio)) { - usleep_range(10, 20); - gpio_set_value_cansleep(pdata->rst_gpio, 0); - usleep_range(10, 20); - gpio_set_value_cansleep(pdata->rst_gpio, 1); - usleep_range(120, 240); - } + usleep_range(10, 20); + gpiod_set_value_cansleep(rst_b, 1); + usleep_range(10, 20); + gpiod_set_value_cansleep(rst_b, 0); + usleep_range(120, 240); /* allocate ieee802154_hw and private data */ hw = ieee802154_alloc_hw(sizeof(*lp), &mcr20a_hw_ops); if (!hw) { dev_crit(&spi->dev, "ieee802154_alloc_hw failed\n"); - ret = -ENOMEM; - goto free_pdata; + return ret; } /* init mcr20a local data */ lp = hw->priv; lp->hw = hw; lp->spi = spi; - lp->spi->dev.platform_data = pdata; - lp->pdata = pdata; /* init ieee802154_hw */ hw->parent = &spi->dev; @@ -1370,8 +1334,6 @@ mcr20a_probe(struct spi_device *spi) free_dev: ieee802154_free_hw(lp->hw); -free_pdata: - kfree(pdata); return ret; } diff --git a/include/linux/dns_resolver.h b/include/linux/dns_resolver.h index 6ac3cad9aef1..34a744a1bafc 100644 --- a/include/linux/dns_resolver.h +++ b/include/linux/dns_resolver.h @@ -24,11 +24,9 @@ #ifndef _LINUX_DNS_RESOLVER_H #define _LINUX_DNS_RESOLVER_H -#ifdef __KERNEL__ +#include <uapi/linux/dns_resolver.h> extern int dns_query(const char *type, const char *name, size_t namelen, const char *options, char **_result, time64_t *_expiry); -#endif /* KERNEL */ - #endif /* _LINUX_DNS_RESOLVER_H */ diff --git a/include/uapi/linux/dns_resolver.h b/include/uapi/linux/dns_resolver.h new file mode 100644 index 000000000000..129745f9c794 --- /dev/null +++ b/include/uapi/linux/dns_resolver.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* DNS resolver interface definitions. + * + * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _UAPI_LINUX_DNS_RESOLVER_H +#define _UAPI_LINUX_DNS_RESOLVER_H + +#include <linux/types.h> + +/* + * Type of payload. + */ +enum dns_payload_content_type { + DNS_PAYLOAD_IS_SERVER_LIST = 0, /* List of servers, requested by srv=1 */ +}; + +/* + * Type of address that might be found in an address record. + */ +enum dns_payload_address_type { + DNS_ADDRESS_IS_IPV4 = 0, /* 4-byte AF_INET address */ + DNS_ADDRESS_IS_IPV6 = 1, /* 16-byte AF_INET6 address */ +}; + +/* + * Type of protocol used to access a server. + */ +enum dns_payload_protocol_type { + DNS_SERVER_PROTOCOL_UNSPECIFIED = 0, + DNS_SERVER_PROTOCOL_UDP = 1, /* Use UDP to talk to the server */ + DNS_SERVER_PROTOCOL_TCP = 2, /* Use TCP to talk to the server */ +}; + +/* + * Source of record included in DNS resolver payload. + */ +enum dns_record_source { + DNS_RECORD_UNAVAILABLE = 0, /* No source available (empty record) */ + DNS_RECORD_FROM_CONFIG = 1, /* From local configuration data */ + DNS_RECORD_FROM_DNS_A = 2, /* From DNS A or AAAA record */ + DNS_RECORD_FROM_DNS_AFSDB = 3, /* From DNS AFSDB record */ + DNS_RECORD_FROM_DNS_SRV = 4, /* From DNS SRV record */ + DNS_RECORD_FROM_NSS = 5, /* From NSS */ + NR__dns_record_source +}; + +/* + * Status of record included in DNS resolver payload. + */ +enum dns_lookup_status { + DNS_LOOKUP_NOT_DONE = 0, /* No lookup has been made */ + DNS_LOOKUP_GOOD = 1, /* Good records obtained */ + DNS_LOOKUP_GOOD_WITH_BAD = 2, /* Good records, some decoding errors */ + DNS_LOOKUP_BAD = 3, /* Couldn't decode results */ + DNS_LOOKUP_GOT_NOT_FOUND = 4, /* Got a "Not Found" result */ + DNS_LOOKUP_GOT_LOCAL_FAILURE = 5, /* Local failure during lookup */ + DNS_LOOKUP_GOT_TEMP_FAILURE = 6, /* Temporary failure during lookup */ + DNS_LOOKUP_GOT_NS_FAILURE = 7, /* Name server failure */ + NR__dns_lookup_status +}; + +/* + * Header at the beginning of binary format payload. + */ +struct dns_payload_header { + __u8 zero; /* Zero byte: marks this as not being text */ + __u8 content; /* enum dns_payload_content_type */ + __u8 version; /* Encoding version */ +} __packed; + +/* + * Header at the beginning of a V1 server list. This is followed directly by + * the server records. Each server records begins with a struct of type + * dns_server_list_v1_server. + */ +struct dns_server_list_v1_header { + struct dns_payload_header hdr; + __u8 source; /* enum dns_record_source */ + __u8 status; /* enum dns_lookup_status */ + __u8 nr_servers; /* Number of server records following this */ +} __packed; + +/* + * Header at the beginning of each V1 server record. This is followed by the + * characters of the name with no NUL-terminator, followed by the address + * records for that server. Each address record begins with a struct of type + * struct dns_server_list_v1_address. + */ +struct dns_server_list_v1_server { + __u16 name_len; /* Length of name (LE) */ + __u16 priority; /* Priority (as SRV record) (LE) */ + __u16 weight; /* Weight (as SRV record) (LE) */ + __u16 port; /* UDP/TCP port number (LE) */ + __u8 source; /* enum dns_record_source */ + __u8 status; /* enum dns_lookup_status */ + __u8 protocol; /* enum dns_payload_protocol_type */ + __u8 nr_addrs; +} __packed; + +/* + * Header at the beginning of each V1 address record. This is followed by the + * bytes of the address, 4 for IPV4 and 16 for IPV6. + */ +struct dns_server_list_v1_address { + __u8 address_type; /* enum dns_payload_address_type */ +} __packed; + +#endif /* _UAPI_LINUX_DNS_RESOLVER_H */ diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index 7f4534828f6c..a65d553e730d 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -29,6 +29,7 @@ #include <linux/keyctl.h> #include <linux/err.h> #include <linux/seq_file.h> +#include <linux/dns_resolver.h> #include <keys/dns_resolver-type.h> #include <keys/user-type.h> #include "internal.h" @@ -48,27 +49,86 @@ const struct cred *dns_resolver_cache; /* * Preparse instantiation data for a dns_resolver key. * - * The data must be a NUL-terminated string, with the NUL char accounted in - * datalen. + * For normal hostname lookups, the data must be a NUL-terminated string, with + * the NUL char accounted in datalen. * * If the data contains a '#' characters, then we take the clause after each * one to be an option of the form 'key=value'. The actual data of interest is * the string leading up to the first '#'. For instance: * * "ip1,ip2,...#foo=bar" + * + * For server list requests, the data must begin with a NUL char and be + * followed by a byte indicating the version of the data format. Version 1 + * looks something like (note this is packed): + * + * u8 Non-string marker (ie. 0) + * u8 Content (DNS_PAYLOAD_IS_*) + * u8 Version (e.g. 1) + * u8 Source of server list + * u8 Lookup status of server list + * u8 Number of servers + * foreach-server { + * __le16 Name length + * __le16 Priority (as per SRV record, low first) + * __le16 Weight (as per SRV record, higher first) + * __le16 Port + * u8 Source of address list + * u8 Lookup status of address list + * u8 Protocol (DNS_SERVER_PROTOCOL_*) + * u8 Number of addresses + * char[] Name (not NUL-terminated) + * foreach-address { + * u8 Family (DNS_ADDRESS_IS_*) + * union { + * u8[4] ipv4_addr + * u8[16] ipv6_addr + * } + * } + * } + * */ static int dns_resolver_preparse(struct key_preparsed_payload *prep) { + const struct dns_payload_header *bin; struct user_key_payload *upayload; unsigned long derrno; int ret; int datalen = prep->datalen, result_len = 0; const char *data = prep->data, *end, *opt; + if (datalen <= 1 || !data) + return -EINVAL; + + if (data[0] == 0) { + /* It may be a server list. */ + if (datalen <= sizeof(*bin)) + return -EINVAL; + + bin = (const struct dns_payload_header *)data; + kenter("[%u,%u],%u", bin->content, bin->version, datalen); + if (bin->content != DNS_PAYLOAD_IS_SERVER_LIST) { + pr_warn_ratelimited( + "dns_resolver: Unsupported content type (%u)\n", + bin->content); + return -EINVAL; + } + + if (bin->version != 1) { + pr_warn_ratelimited( + "dns_resolver: Unsupported server list version (%u)\n", + bin->version); + return -EINVAL; + } + + result_len = datalen; + goto store_result; + } + kenter("'%*.*s',%u", datalen, datalen, data, datalen); - if (datalen <= 1 || !data || data[datalen - 1] != '\0') + if (!data || data[datalen - 1] != '\0') return -EINVAL; datalen--; @@ -144,6 +204,7 @@ dns_resolver_preparse(struct key_preparsed_payload *prep) return 0; } +store_result: kdebug("store result"); prep->quotalen = result_len; diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c index 49da67034f29..76338c38738a 100644 --- a/net/dns_resolver/dns_query.c +++ b/net/dns_resolver/dns_query.c @@ -148,12 +148,9 @@ int dns_query(const char *type, const char *name, size_t namelen, if (_result) { ret = -ENOMEM; - *_result = kmalloc(len + 1, GFP_KERNEL); + *_result = kmemdup_nul(upayload->data, len, GFP_KERNEL); if (!*_result) goto put; - - memcpy(*_result, upayload->data, len); - (*_result)[len] = '\0'; } if (_expiry) |