Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (49 commits)
  [SCTP]: Set assoc_id correctly during INIT collision.
  [SCTP]: Re-order SCTP initializations to avoid race with sctp_rcv()
  [SCTP]: Fix the SO_REUSEADDR handling to be similar to TCP.
  [SCTP]: Verify all destination ports in sctp_connectx.
  [XFRM] SPD info TLV aggregation
  [XFRM] SAD info TLV aggregationx
  [AF_RXRPC]: Sort out MTU handling.
  [AF_IUCV/IUCV] : Add missing section annotations
  [AF_IUCV]: Implementation of a skb backlog queue
  [NETLINK]: Remove bogus BUG_ON
  [IPV6]: Some cleanups in include/net/ipv6.h
  [TCP]: zero out rx_opt in tcp_disconnect()
  [BNX2]: Fix TSO problem with small MSS.
  [NET]: Rework dev_base via list_head (v3)
  [TCP] Highspeed: Limited slow-start is nowadays in tcp_slow_start
  [BNX2]: Update version and reldate.
  [BNX2]: Print bus information for PCIE devices.
  [BNX2]: Add 1-shot MSI handler for 5709.
  [BNX2]: Restructure PHY event handling.
  [BNX2]: Add indirect spinlock.
  ...
This commit is contained in:
Linus Torvalds committed 2007-05-04 19:36:58 -07:00
commit 7e20ef030d
84 files changed
+6838 -6151

No files matched your search

+1 -1
View File
@@ -107,7 +107,7 @@ static void appldata_get_net_sum_data(void *data)
tx_dropped = 0;
collisions = 0;
read_lock(&dev_base_lock);
for (dev = dev_base; dev != NULL; dev = dev->next) {
for_each_netdev(dev) {
stats = dev->get_stats(dev);
rx_packets += stats->rx_packets;
tx_packets += stats->tx_packets;
+2 -1
View File
@@ -686,7 +686,8 @@ static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg)
int i = 0;
read_lock_bh(&dev_base_lock);
for (d = dev_base; d; d = d->next) i++;
for_each_netdev(d)
i++;
read_unlock_bh(&dev_base_lock);
if (put_user (i, (int __user *)A(arg)))
+5 -3
View File
@@ -194,15 +194,15 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
sl = sl_tail = NULL;
read_lock(&dev_base_lock);
for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) {
for_each_netdev(ifp) {
dev_hold(ifp);
if (!is_aoe_netif(ifp))
continue;
goto cont;
skb = new_skb(sizeof *h + sizeof *ch);
if (skb == NULL) {
printk(KERN_INFO "aoe: skb alloc failure\n");
continue;
goto cont;
}
skb_put(skb, sizeof *h + sizeof *ch);
skb->dev = ifp;
@@ -221,6 +221,8 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
skb->next = sl;
sl = skb;
cont:
dev_put(ifp);
}
read_unlock(&dev_base_lock);
+736 -322
View File
File diff suppressed because it is too large. Load diff
+57 -8
View File
@@ -1,6 +1,6 @@
/* bnx2.h: Broadcom NX2 network driver.
*
* Copyright (c) 2004, 2005, 2006 Broadcom Corporation
* Copyright (c) 2004-2007 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,8 +24,11 @@ struct tx_bd {
u32 tx_bd_haddr_hi;
u32 tx_bd_haddr_lo;
u32 tx_bd_mss_nbytes;
#define TX_BD_TCP6_OFF2_SHL (14)
u32 tx_bd_vlan_tag_flags;
#define TX_BD_FLAGS_CONN_FAULT (1<<0)
#define TX_BD_FLAGS_TCP6_OFF0_MSK (3<<1)
#define TX_BD_FLAGS_TCP6_OFF0_SHL (1)
#define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1)
#define TX_BD_FLAGS_IP_CKSUM (1<<2)
#define TX_BD_FLAGS_VLAN_TAG (1<<3)
@@ -34,6 +37,7 @@ struct tx_bd {
#define TX_BD_FLAGS_END (1<<6)
#define TX_BD_FLAGS_START (1<<7)
#define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8)
#define TX_BD_FLAGS_TCP6_OFF4_SHL (12)
#define TX_BD_FLAGS_SW_FLAGS (1<<13)
#define TX_BD_FLAGS_SW_SNAP (1<<14)
#define TX_BD_FLAGS_SW_LSO (1<<15)
@@ -6292,6 +6296,41 @@ struct l2_fhdr {
#define MII_BNX2_DSP_ADDRESS 0x17
#define MII_BNX2_DSP_EXPAND_REG 0x0f00
#define MII_BNX2_BLK_ADDR 0x1f
#define MII_BNX2_BLK_ADDR_IEEE0 0x0000
#define MII_BNX2_BLK_ADDR_GP_STATUS 0x8120
#define MII_BNX2_GP_TOP_AN_STATUS1 0x1b
#define MII_BNX2_GP_TOP_AN_SPEED_MSK 0x3f00
#define MII_BNX2_GP_TOP_AN_SPEED_10 0x0000
#define MII_BNX2_GP_TOP_AN_SPEED_100 0x0100
#define MII_BNX2_GP_TOP_AN_SPEED_1G 0x0200
#define MII_BNX2_GP_TOP_AN_SPEED_2_5G 0x0300
#define MII_BNX2_GP_TOP_AN_SPEED_1GKV 0x0d00
#define MII_BNX2_GP_TOP_AN_FD 0x8
#define MII_BNX2_BLK_ADDR_SERDES_DIG 0x8300
#define MII_BNX2_SERDES_DIG_1000XCTL1 0x10
#define MII_BNX2_SD_1000XCTL1_FIBER 0x01
#define MII_BNX2_SD_1000XCTL1_AUTODET 0x10
#define MII_BNX2_SERDES_DIG_MISC1 0x18
#define MII_BNX2_SD_MISC1_FORCE_MSK 0xf
#define MII_BNX2_SD_MISC1_FORCE_2_5G 0x0
#define MII_BNX2_SD_MISC1_FORCE 0x10
#define MII_BNX2_BLK_ADDR_OVER1G 0x8320
#define MII_BNX2_OVER1G_UP1 0x19
#define MII_BNX2_BLK_ADDR_BAM_NXTPG 0x8350
#define MII_BNX2_BAM_NXTPG_CTL 0x10
#define MII_BNX2_NXTPG_CTL_BAM 0x1
#define MII_BNX2_NXTPG_CTL_T2 0x2
#define MII_BNX2_BLK_ADDR_CL73_USERB0 0x8370
#define MII_BNX2_CL73_BAM_CTL1 0x12
#define MII_BNX2_CL73_BAM_EN 0x8000
#define MII_BNX2_CL73_BAM_STA_MGR_EN 0x4000
#define MII_BNX2_CL73_BAM_NP_AFT_BP_EN 0x2000
#define MII_BNX2_BLK_ADDR_AER 0xffd0
#define MII_BNX2_AER_AER 0x1e
#define MII_BNX2_AER_AER_AN_MMD 0x3800
#define MII_BNX2_BLK_ADDR_COMBO_IEEEB0 0xffe0
#define MIN_ETHERNET_PACKET_SIZE 60
#define MAX_ETHERNET_PACKET_SIZE 1514
#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
@@ -6429,13 +6468,15 @@ struct bnx2 {
u32 last_status_idx;
u32 flags;
#define PCIX_FLAG 1
#define PCI_32BIT_FLAG 2
#define ONE_TDMA_FLAG 4 /* no longer used */
#define NO_WOL_FLAG 8
#define USING_DAC_FLAG 0x10
#define USING_MSI_FLAG 0x20
#define ASF_ENABLE_FLAG 0x40
#define PCIX_FLAG 0x00000001
#define PCI_32BIT_FLAG 0x00000002
#define ONE_TDMA_FLAG 0x00000004 /* no longer used */
#define NO_WOL_FLAG 0x00000008
#define USING_MSI_FLAG 0x00000020
#define ASF_ENABLE_FLAG 0x00000040
#define MSI_CAP_FLAG 0x00000080
#define ONE_SHOT_MSI_FLAG 0x00000100
#define PCIE_FLAG 0x00000200
/* Put tx producer and consumer fields in separate cache lines. */
@@ -6484,6 +6525,7 @@ struct bnx2 {
/* Used to synchronize phy accesses. */
spinlock_t phy_lock;
spinlock_t indirect_lock;
u32 phy_flags;
#define PHY_SERDES_FLAG 1
@@ -6495,6 +6537,13 @@ struct bnx2 {
#define PHY_INT_MODE_LINK_READY_FLAG 0x200
#define PHY_DIS_EARLY_DAC_FLAG 0x400
u32 mii_bmcr;
u32 mii_bmsr;
u32 mii_bmsr1;
u32 mii_adv;
u32 mii_lpa;
u32 mii_up1;
u32 chip_id;
/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
#define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000)
+1044 -653
View File
File diff suppressed because it is too large. Load diff
+3938 -3930
View File
File diff suppressed because it is too large. Load diff
+1 -3
View File
@@ -1971,8 +1971,7 @@ static struct net_device *get_strip_dev(struct strip *strip_info)
sizeof(zero_address))) {
struct net_device *dev;
read_lock_bh(&dev_base_lock);
dev = dev_base;
while (dev) {
for_each_netdev(dev) {
if (dev->type == strip_info->dev->type &&
!memcmp(dev->dev_addr,
&strip_info->true_dev_addr,
@@ -1983,7 +1982,6 @@ static struct net_device *get_strip_dev(struct strip *strip_info)
read_unlock_bh(&dev_base_lock);
return (dev);
}
dev = dev->next;
}
read_unlock_bh(&dev_base_lock);
}
+1 -1
View File
@@ -365,7 +365,7 @@ static __inline__ int led_get_net_activity(void)
* for reading should be OK */
read_lock(&dev_base_lock);
rcu_read_lock();
for (dev = dev_base; dev; dev = dev->next) {
for_each_netdev(dev) {
struct net_device_stats *stats;
struct in_device *in_dev = __in_dev_get_rcu(dev);
if (!in_dev || !in_dev->ifa_list)
-1
View File
@@ -2020,7 +2020,6 @@ config AFS_FS
tristate "Andrew File System support (AFS) (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL
select AF_RXRPC
select KEYS
help
If you say Y here, you will get an experimental Andrew File System
driver. It currently only supports unsecured read-only AFS access.
+1 -1
View File
@@ -18,7 +18,7 @@ kafs-objs := \
security.o \
server.o \
super.o \
use-rtnetlink.o \
netdevices.o \
vlclient.o \
vlocation.o \
vnode.o \
+1 -1
View File
@@ -468,7 +468,7 @@ int __init afs_callback_update_init(void)
/*
* shut down the callback update process
*/
void __exit afs_callback_update_kill(void)
void afs_callback_update_kill(void)
{
destroy_workqueue(afs_callback_update_worker);
}
+1
View File
@@ -443,6 +443,7 @@ static void SRXAFSCB_GetCapabilities(struct work_struct *work)
reply.ia.netmask[loop] = ifs[loop].netmask.s_addr;
reply.ia.mtu[loop] = htonl(ifs[loop].mtu);
}
kfree(ifs);
}
reply.cap.capcount = htonl(1);
+2 -1
View File
@@ -266,7 +266,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
call->unmarshall++;
if (call->count < PAGE_SIZE) {
buffer = kmap_atomic(call->reply3, KM_USER0);
page = call->reply3;
buffer = kmap_atomic(page, KM_USER0);
memset(buffer + PAGE_SIZE - call->count, 0,
call->count);
kunmap_atomic(buffer, KM_USER0);
+3 -4
View File
@@ -349,7 +349,6 @@ struct afs_permits {
* record of one of a system's set of network interfaces
*/
struct afs_interface {
unsigned index; /* interface index */
struct in_addr address; /* IPv4 address bound to interface */
struct in_addr netmask; /* netmask applied to address */
unsigned mtu; /* MTU of interface */
@@ -392,7 +391,7 @@ extern void afs_give_up_callback(struct afs_vnode *);
extern void afs_dispatch_give_up_callbacks(struct work_struct *);
extern void afs_flush_callback_breaks(struct afs_server *);
extern int __init afs_callback_update_init(void);
extern void __exit afs_callback_update_kill(void);
extern void afs_callback_update_kill(void);
/*
* cell.c
@@ -564,7 +563,7 @@ extern void afs_fs_exit(void);
* use-rtnetlink.c
*/
extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool);
extern int afs_get_MAC_address(u8 [6]);
extern int afs_get_MAC_address(u8 *, size_t);
/*
* vlclient.c
@@ -591,7 +590,7 @@ extern struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *,
struct key *,
const char *, size_t);
extern void afs_put_vlocation(struct afs_vlocation *);
extern void __exit afs_vlocation_purge(void);
extern void afs_vlocation_purge(void);
/*
* vnode.c
+1 -1
View File
@@ -54,7 +54,7 @@ static int __init afs_get_client_UUID(void)
/* read the MAC address of one of the external interfaces and construct
* a UUID from it */
ret = afs_get_MAC_address(afs_uuid.node);
ret = afs_get_MAC_address(afs_uuid.node, sizeof(afs_uuid.node));
if (ret < 0)
return ret;
+68
View File
@@ -0,0 +1,68 @@
/* AFS network device helpers
*
* Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
*/
#include <linux/string.h>
#include <linux/rtnetlink.h>
#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include "internal.h"
/*
* get a MAC address from a random ethernet interface that has a real one
* - the buffer will normally be 6 bytes in size
*/
int afs_get_MAC_address(u8 *mac, size_t maclen)
{
struct net_device *dev;
int ret = -ENODEV;
if (maclen != ETH_ALEN)
BUG();
rtnl_lock();
dev = __dev_getfirstbyhwtype(ARPHRD_ETHER);
if (dev) {
memcpy(mac, dev->dev_addr, maclen);
ret = 0;
}
rtnl_unlock();
return ret;
}
/*
* get a list of this system's interface IPv4 addresses, netmasks and MTUs
* - maxbufs must be at least 1
* - returns the number of interface records in the buffer
*/
int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
bool wantloopback)
{
struct net_device *dev;
struct in_device *idev;
int n = 0;
ASSERT(maxbufs > 0);
rtnl_lock();
for_each_netdev(dev) {
if (dev->type == ARPHRD_LOOPBACK && !wantloopback)
continue;
idev = __in_dev_get_rtnl(dev);
if (!idev)
continue;
for_primary_ifa(idev) {
bufs[n].address.s_addr = ifa->ifa_address;
bufs[n].netmask.s_addr = ifa->ifa_mask;
bufs[n].mtu = dev->mtu;
n++;
if (n >= maxbufs)
goto out;
} endfor_ifa(idev);
}
out:
rtnl_unlock();
return n;
}
+43 -57
View File
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/parser.h>
#include "internal.h"
#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
@@ -42,7 +43,7 @@ struct file_system_type afs_fs_type = {
.name = "afs",
.get_sb = afs_get_sb,
.kill_sb = kill_anon_super,
.fs_flags = FS_BINARY_MOUNTDATA,
.fs_flags = 0,
};
static const struct super_operations afs_super_ops = {
@@ -58,6 +59,20 @@ static const struct super_operations afs_super_ops = {
static struct kmem_cache *afs_inode_cachep;
static atomic_t afs_count_active_inodes;
enum {
afs_no_opt,
afs_opt_cell,
afs_opt_rwpath,
afs_opt_vol,
};
static const match_table_t afs_options_list = {
{ afs_opt_cell, "cell=%s" },
{ afs_opt_rwpath, "rwpath" },
{ afs_opt_vol, "vol=%s" },
{ afs_no_opt, NULL },
};
/*
* initialise the filesystem
*/
@@ -114,31 +129,6 @@ void __exit afs_fs_exit(void)
_leave("");
}
/*
* check that an argument has a value
*/
static int want_arg(char **_value, const char *option)
{
if (!_value || !*_value || !**_value) {
printk(KERN_NOTICE "kAFS: %s: argument missing\n", option);
return 0;
}
return 1;
}
/*
* check that there's no subsequent value
*/
static int want_no_value(char *const *_value, const char *option)
{
if (*_value && **_value) {
printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n",
option, *_value);
return 0;
}
return 1;
}
/*
* parse the mount options
* - this function has been shamelessly adapted from the ext3 fs which
@@ -148,48 +138,46 @@ static int afs_parse_options(struct afs_mount_params *params,
char *options, const char **devname)
{
struct afs_cell *cell;
char *key, *value;
int ret;
substring_t args[MAX_OPT_ARGS];
char *p;
int token;
_enter("%s", options);
options[PAGE_SIZE - 1] = 0;
ret = 0;
while ((key = strsep(&options, ","))) {
value = strchr(key, '=');
if (value)
*value++ = 0;
while ((p = strsep(&options, ","))) {
if (!*p)
continue;
_debug("kAFS: KEY: %s, VAL:%s", key, value ?: "-");
if (strcmp(key, "rwpath") == 0) {
if (!want_no_value(&value, "rwpath"))
return -EINVAL;
params->rwpath = 1;
} else if (strcmp(key, "vol") == 0) {
if (!want_arg(&value, "vol"))
return -EINVAL;
*devname = value;
} else if (strcmp(key, "cell") == 0) {
if (!want_arg(&value, "cell"))
return -EINVAL;
cell = afs_cell_lookup(value, strlen(value));
token = match_token(p, afs_options_list, args);
switch (token) {
case afs_opt_cell:
cell = afs_cell_lookup(args[0].from,
args[0].to - args[0].from);
if (IS_ERR(cell))
return PTR_ERR(cell);
afs_put_cell(params->cell);
params->cell = cell;
} else {
printk("kAFS: Unknown mount option: '%s'\n", key);
ret = -EINVAL;
goto error;
break;
case afs_opt_rwpath:
params->rwpath = 1;
break;
case afs_opt_vol:
*devname = args[0].from;
break;
default:
printk(KERN_ERR "kAFS:"
" Unknown or invalid mount option: '%s'\n", p);
return -EINVAL;
}
}
ret = 0;
error:
_leave(" = %d", ret);
return ret;
_leave(" = 0");
return 0;
}
/*
@@ -361,7 +349,6 @@ error:
/*
* get an AFS superblock
* - TODO: don't use get_sb_nodev(), but rather call sget() directly
*/
static int afs_get_sb(struct file_system_type *fs_type,
int flags,
@@ -386,7 +373,6 @@ static int afs_get_sb(struct file_system_type *fs_type,
goto error;
}
ret = afs_parse_device_name(&params, dev_name);
if (ret < 0)
goto error;
-473
View File
@@ -1,473 +0,0 @@
/* RTNETLINK client
*
* Copyright (C) 2007 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 License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if_addr.h>
#include <linux/if_arp.h>
#include <linux/inetdevice.h>
#include <net/netlink.h>
#include "internal.h"
struct afs_rtm_desc {
struct socket *nlsock;
struct afs_interface *bufs;
u8 *mac;
size_t nbufs;
size_t maxbufs;
void *data;
ssize_t datalen;
size_t datamax;
int msg_seq;
unsigned mac_index;
bool wantloopback;
int (*parse)(struct afs_rtm_desc *, struct nlmsghdr *);
};
/*
* parse an RTM_GETADDR response
*/
static int afs_rtm_getaddr_parse(struct afs_rtm_desc *desc,
struct nlmsghdr *nlhdr)
{
struct afs_interface *this;
struct ifaddrmsg *ifa;
struct rtattr *rtattr;
const char *name;
size_t len;
ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr);
_enter("{ix=%d,af=%d}", ifa->ifa_index, ifa->ifa_family);
if (ifa->ifa_family != AF_INET) {
_leave(" = 0 [family %d]", ifa->ifa_family);
return 0;
}
if (desc->nbufs >= desc->maxbufs) {
_leave(" = 0 [max %zu/%zu]", desc->nbufs, desc->maxbufs);
return 0;
}
this = &desc->bufs[desc->nbufs];
this->index = ifa->ifa_index;
this->netmask.s_addr = inet_make_mask(ifa->ifa_prefixlen);
this->mtu = 0;
rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifaddrmsg));
len = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifaddrmsg));
name = "unknown";
for (; RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) {
switch (rtattr->rta_type) {
case IFA_ADDRESS:
memcpy(&this->address, RTA_DATA(rtattr), 4);
break;
case IFA_LABEL:
name = RTA_DATA(rtattr);
break;
}
}
_debug("%s: "NIPQUAD_FMT"/"NIPQUAD_FMT,
name, NIPQUAD(this->address), NIPQUAD(this->netmask));
desc->nbufs++;
_leave(" = 0");
return 0;
}
/*
* parse an RTM_GETLINK response for MTUs
*/
static int afs_rtm_getlink_if_parse(struct afs_rtm_desc *desc,
struct nlmsghdr *nlhdr)
{
struct afs_interface *this;
struct ifinfomsg *ifi;
struct rtattr *rtattr;
const char *name;
size_t len, loop;
ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr);
_enter("{ix=%d}", ifi->ifi_index);
for (loop = 0; loop < desc->nbufs; loop++) {
this = &desc->bufs[loop];
if (this->index == ifi->ifi_index)
goto found;
}
_leave(" = 0 [no match]");
return 0;
found:
if (ifi->ifi_type == ARPHRD_LOOPBACK && !desc->wantloopback) {
_leave(" = 0 [loopback]");
return 0;
}
rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifinfomsg));
len = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifinfomsg));
name = "unknown";
for (; RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) {
switch (rtattr->rta_type) {
case IFLA_MTU:
memcpy(&this->mtu, RTA_DATA(rtattr), 4);
break;
case IFLA_IFNAME:
name = RTA_DATA(rtattr);
break;
}
}
_debug("%s: "NIPQUAD_FMT"/"NIPQUAD_FMT" mtu %u",
name, NIPQUAD(this->address), NIPQUAD(this->netmask),
this->mtu);
_leave(" = 0");
return 0;
}
/*
* parse an RTM_GETLINK response for the MAC address belonging to the lowest
* non-internal interface
*/
static int afs_rtm_getlink_mac_parse(struct afs_rtm_desc *desc,
struct nlmsghdr *nlhdr)
{
struct ifinfomsg *ifi;
struct rtattr *rtattr;
const char *name;
size_t remain, len;
bool set;
ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr);
_enter("{ix=%d}", ifi->ifi_index);
if (ifi->ifi_index >= desc->mac_index) {
_leave(" = 0 [high]");
return 0;
}
if (ifi->ifi_type == ARPHRD_LOOPBACK) {
_leave(" = 0 [loopback]");
return 0;
}
rtattr = NLMSG_DATA(nlhdr) + NLMSG_ALIGN(sizeof(struct ifinfomsg));
remain = NLMSG_PAYLOAD(nlhdr, sizeof(struct ifinfomsg));
name = "unknown";
set = false;
for (; RTA_OK(rtattr, remain); rtattr = RTA_NEXT(rtattr, remain)) {
switch (rtattr->rta_type) {
case IFLA_ADDRESS:
len = RTA_PAYLOAD(rtattr);
memcpy(desc->mac, RTA_DATA(rtattr),
min_t(size_t, len, 6));
desc->mac_index = ifi->ifi_index;
set = true;
break;
case IFLA_IFNAME:
name = RTA_DATA(rtattr);
break;
}
}
if (set)
_debug("%s: %02x:%02x:%02x:%02x:%02x:%02x",
name,
desc->mac[0], desc->mac[1], desc->mac[2],
desc->mac[3], desc->mac[4], desc->mac[5]);
_leave(" = 0");
return 0;
}
/*
* read the rtnetlink response and pass to parsing routine
*/
static int afs_read_rtm(struct afs_rtm_desc *desc)
{
struct nlmsghdr *nlhdr, tmphdr;
struct msghdr msg;
struct kvec iov[1];
void *data;
bool last = false;
int len, ret, remain;
_enter("");
do {
/* first of all peek to see how big the packet is */
memset(&msg, 0, sizeof(msg));
iov[0].iov_base = &tmphdr;
iov[0].iov_len = sizeof(tmphdr);
len = kernel_recvmsg(desc->nlsock, &msg, iov, 1,
sizeof(tmphdr), MSG_PEEK | MSG_TRUNC);
if (len < 0) {
_leave(" = %d [peek]", len);
return len;
}
if (len == 0)
continue;
if (len < sizeof(tmphdr) || len < NLMSG_PAYLOAD(&tmphdr, 0)) {
_leave(" = -EMSGSIZE");
return -EMSGSIZE;
}
if (desc->datamax < len) {
kfree(desc->data);
desc->data = NULL;
data = kmalloc(len, GFP_KERNEL);
if (!data)
return -ENOMEM;
desc->data = data;
}
desc->datamax = len;
/* read all the data from this packet */
iov[0].iov_base = desc->data;
iov[0].iov_len = desc->datamax;
desc->datalen = kernel_recvmsg(desc->nlsock, &msg, iov, 1,
desc->datamax, 0);
if (desc->datalen < 0) {
_leave(" = %zd [recv]", desc->datalen);
return desc->datalen;
}
nlhdr = desc->data;
/* check if the header is valid */
if (!NLMSG_OK(nlhdr, desc->datalen) ||
nlhdr->nlmsg_type == NLMSG_ERROR) {
_leave(" = -EIO");
return -EIO;
}
/* see if this is the last message */
if (nlhdr->nlmsg_type == NLMSG_DONE ||
!(nlhdr->nlmsg_flags & NLM_F_MULTI))
last = true;
/* parse the bits we got this time */
nlmsg_for_each_msg(nlhdr, desc->data, desc->datalen, remain) {
ret = desc->parse(desc, nlhdr);
if (ret < 0) {
_leave(" = %d [parse]", ret);
return ret;
}
}
} while (!last);
_leave(" = 0");
return 0;
}
/*
* list the interface bound addresses to get the address and netmask
*/
static int afs_rtm_getaddr(struct afs_rtm_desc *desc)
{
struct msghdr msg;
struct kvec iov[1];
int ret;
struct {
struct nlmsghdr nl_msg __attribute__((aligned(NLMSG_ALIGNTO)));
struct ifaddrmsg addr_msg __attribute__((aligned(NLMSG_ALIGNTO)));
} request;
_enter("");
memset(&request, 0, sizeof(request));
request.nl_msg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
request.nl_msg.nlmsg_type = RTM_GETADDR;
request.nl_msg.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
request.nl_msg.nlmsg_seq = desc->msg_seq++;
request.nl_msg.nlmsg_pid = 0;
memset(&msg, 0, sizeof(msg));
iov[0].iov_base = &request;
iov[0].iov_len = sizeof(request);
ret = kernel_sendmsg(desc->nlsock, &msg, iov, 1, iov[0].iov_len);
_leave(" = %d", ret);
return ret;
}
/*
* list the interface link statuses to get the MTUs
*/
static int afs_rtm_getlink(struct afs_rtm_desc *desc)
{
struct msghdr msg;
struct kvec iov[1];
int ret;
struct {
struct nlmsghdr nl_msg __attribute__((aligned(NLMSG_ALIGNTO)));
struct ifinfomsg link_msg __attribute__((aligned(NLMSG_ALIGNTO)));
} request;
_enter("");
memset(&request, 0, sizeof(request));
request.nl_msg.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
request.nl_msg.nlmsg_type = RTM_GETLINK;
request.nl_msg.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
request.nl_msg.nlmsg_seq = desc->msg_seq++;
request.nl_msg.nlmsg_pid = 0;
memset(&msg, 0, sizeof(msg));
iov[0].iov_base = &request;
iov[0].iov_len = sizeof(request);
ret = kernel_sendmsg(desc->nlsock, &msg, iov, 1, iov[0].iov_len);
_leave(" = %d", ret);
return ret;
}
/*
* cull any interface records for which there isn't an MTU value
*/
static void afs_cull_interfaces(struct afs_rtm_desc *desc)
{
struct afs_interface *bufs = desc->bufs;
size_t nbufs = desc->nbufs;
int loop, point = 0;
_enter("{%zu}", nbufs);
for (loop = 0; loop < nbufs; loop++) {
if (desc->bufs[loop].mtu != 0) {
if (loop != point) {
ASSERTCMP(loop, >, point);
bufs[point] = bufs[loop];
}
point++;
}
}
desc->nbufs = point;
_leave(" [%zu/%zu]", desc->nbufs, nbufs);
}
/*
* get a list of this system's interface IPv4 addresses, netmasks and MTUs
* - returns the number of interface records in the buffer
*/
int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
bool wantloopback)
{
struct afs_rtm_desc desc;
int ret, loop;
_enter("");
memset(&desc, 0, sizeof(desc));
desc.bufs = bufs;
desc.maxbufs = maxbufs;
desc.wantloopback = wantloopback;
ret = sock_create_kern(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE,
&desc.nlsock);
if (ret < 0) {
_leave(" = %d [sock]", ret);
return ret;
}
/* issue RTM_GETADDR */
desc.parse = afs_rtm_getaddr_parse;
ret = afs_rtm_getaddr(&desc);
if (ret < 0)
goto error;
ret = afs_read_rtm(&desc);
if (ret < 0)
goto error;
/* issue RTM_GETLINK */
desc.parse = afs_rtm_getlink_if_parse;
ret = afs_rtm_getlink(&desc);
if (ret < 0)
goto error;
ret = afs_read_rtm(&desc);
if (ret < 0)
goto error;
afs_cull_interfaces(&desc);
ret = desc.nbufs;
for (loop = 0; loop < ret; loop++)
_debug("[%d] "NIPQUAD_FMT"/"NIPQUAD_FMT" mtu %u",
bufs[loop].index,
NIPQUAD(bufs[loop].address),
NIPQUAD(bufs[loop].netmask),
bufs[loop].mtu);
error:
kfree(desc.data);
sock_release(desc.nlsock);
_leave(" = %d", ret);
return ret;
}
/*
* get a MAC address from a random ethernet interface that has a real one
* - the buffer should be 6 bytes in size
*/
int afs_get_MAC_address(u8 mac[6])
{
struct afs_rtm_desc desc;
int ret;
_enter("");
memset(&desc, 0, sizeof(desc));
desc.mac = mac;
desc.mac_index = UINT_MAX;
ret = sock_create_kern(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE,
&desc.nlsock);
if (ret < 0) {
_leave(" = %d [sock]", ret);
return ret;
}
/* issue RTM_GETLINK */
desc.parse = afs_rtm_getlink_mac_parse;
ret = afs_rtm_getlink(&desc);
if (ret < 0)
goto error;
ret = afs_read_rtm(&desc);
if (ret < 0)
goto error;
if (desc.mac_index < UINT_MAX) {
/* got a MAC address */
_debug("[%d] %02x:%02x:%02x:%02x:%02x:%02x",
desc.mac_index,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} else {
ret = -ENONET;
}
error:
sock_release(desc.nlsock);
_leave(" = %d", ret);
return ret;
}
+1 -1
View File
@@ -602,7 +602,7 @@ int __init afs_vlocation_update_init(void)
/*
* discard all the volume location records for rmmod
*/
void __exit afs_vlocation_purge(void)
void afs_vlocation_purge(void)
{
afs_vlocation_timeout = 0;
Loaded 20 of 84 files, more files were not shown because too many files have changed in this diff. Show more