]>
git.proxmox.com Git - mirror_ovs.git/blob - datapath/brc_procfs.c
2 * Copyright (c) 2009, 2010 Nicira Networks.
3 * Distributed under the terms of the GNU GPL version 2.
5 * Significant portions of this file may be copied from parts of the Linux
6 * kernel, by Linus Torvalds and others.
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/netdevice.h>
12 #include <linux/proc_fs.h>
13 #include <linux/seq_file.h>
14 #include <net/genetlink.h>
15 #include "brc_procfs.h"
16 #include "openvswitch/brcompat-netlink.h"
18 /* This code implements a Generic Netlink command BRC_GENL_C_SET_PROC that can
19 * be used to add, modify, and delete arbitrary files in selected
20 * subdirectories of /proc. It's a horrible kluge prompted by the need to
21 * simulate certain /proc/net/vlan and /proc/net/bonding files for software
22 * that wants to read them, and with any luck it will go away eventually.
24 * The implementation is a kluge too. In particular, we want to release the
25 * strings copied into the 'data' members of proc_dir_entry when the
26 * proc_dir_entry structures are freed, but there doesn't appear to be a way to
27 * hook that, so instead we have to rely on being the only entity modifying the
28 * directories in question.
31 static int brc_seq_show(struct seq_file
*seq
, void *unused
)
33 seq_puts(seq
, seq
->private);
37 static int brc_seq_open(struct inode
*inode
, struct file
*file
)
39 return single_open(file
, brc_seq_show
, PDE(inode
)->data
);
42 static struct file_operations brc_fops
= {
47 .release
= single_release
,
50 static struct proc_dir_entry
*proc_vlan_dir
;
51 static struct proc_dir_entry
*proc_bonding_dir
;
53 static struct proc_dir_entry
*brc_lookup_entry(struct proc_dir_entry
*de
, const char *name
)
55 int namelen
= strlen(name
);
56 for (de
= de
->subdir
; de
; de
= de
->next
) {
57 if (de
->namelen
!= namelen
)
59 if (!memcmp(name
, de
->name
, de
->namelen
))
65 static struct proc_dir_entry
*brc_open_dir(const char *dir_name
,
66 struct proc_dir_entry
*parent
,
67 struct proc_dir_entry
**dirp
)
70 struct proc_dir_entry
*dir
;
71 if (brc_lookup_entry(parent
, dir_name
)) {
72 printk(KERN_WARNING
"%s proc directory exists, can't "
73 "simulate--probably its real module is "
74 "loaded\n", dir_name
);
77 dir
= *dirp
= proc_mkdir(dir_name
, parent
);
82 /* Maximum length of the BRC_GENL_A_PROC_DIR and BRC_GENL_A_PROC_NAME strings.
83 * If we could depend on supporting NLA_NUL_STRING and the .len member in
84 * Generic Netlink policy, then we could just put this in brc_genl_policy (and
85 * simplify brc_genl_set_proc() below too), but upstream 2.6.18 does not have
87 #define BRC_NAME_LEN_MAX 32
89 int brc_genl_set_proc(struct sk_buff
*skb
, struct genl_info
*info
)
91 struct proc_dir_entry
*dir
, *entry
;
92 const char *dir_name
, *name
;
95 if (!info
->attrs
[BRC_GENL_A_PROC_DIR
] ||
96 VERIFY_NUL_STRING(info
->attrs
[BRC_GENL_A_PROC_DIR
]) ||
97 !info
->attrs
[BRC_GENL_A_PROC_NAME
] ||
98 VERIFY_NUL_STRING(info
->attrs
[BRC_GENL_A_PROC_NAME
]) ||
99 (info
->attrs
[BRC_GENL_A_PROC_DATA
] &&
100 VERIFY_NUL_STRING(info
->attrs
[BRC_GENL_A_PROC_DATA
])))
103 dir_name
= nla_data(info
->attrs
[BRC_GENL_A_PROC_DIR
]);
104 name
= nla_data(info
->attrs
[BRC_GENL_A_PROC_NAME
]);
105 if (strlen(dir_name
) > BRC_NAME_LEN_MAX
||
106 strlen(name
) > BRC_NAME_LEN_MAX
)
109 if (!strcmp(dir_name
, "net/vlan"))
110 dir
= brc_open_dir("vlan", proc_net
, &proc_vlan_dir
);
111 else if (!strcmp(dir_name
, "net/bonding"))
112 dir
= brc_open_dir("bonding", proc_net
, &proc_bonding_dir
);
116 /* Probably failed because the module that really implements
117 * the function in question is loaded and already owns the
118 * directory in question.*/
122 entry
= brc_lookup_entry(dir
, name
);
123 if (!info
->attrs
[BRC_GENL_A_PROC_DATA
]) {
128 remove_proc_entry(name
, dir
);
129 if (brc_lookup_entry(dir
, name
))
130 return -EBUSY
; /* Shouldn't happen */
134 data
= kstrdup(nla_data(info
->attrs
[BRC_GENL_A_PROC_DATA
]),
140 char *old_data
= entry
->data
;
146 entry
= create_proc_entry(name
, S_IFREG
|S_IRUSR
|S_IWUSR
, dir
);
151 entry
->proc_fops
= &brc_fops
;
157 static void kill_proc_dir(const char *dir_name
,
158 struct proc_dir_entry
*parent
,
159 struct proc_dir_entry
*dir
)
164 struct proc_dir_entry
*e
;
166 char name
[BRC_NAME_LEN_MAX
+ 1];
172 if (e
->namelen
>= sizeof name
) {
173 /* Can't happen: we prevent adding names this long by
174 * limiting the BRC_GENL_A_PROC_NAME string to
175 * BRC_NAME_LEN_MAX bytes. */
179 strcpy(name
, e
->name
);
185 remove_proc_entry(name
, dir
);
187 remove_proc_entry(dir_name
, parent
);
190 void brc_procfs_exit(void)
192 kill_proc_dir("vlan", proc_net
, proc_vlan_dir
);
193 kill_proc_dir("bonding", proc_net
, proc_bonding_dir
);