aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-03-12 17:35:37 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:25:04 -0400
commit0e1256ffd1ec654b35e023c66f6b262d4cba91e9 (patch)
treed949e9d2dfcd9bb94b47e9a3a63f2afe09d2ec79 /net/core/dev.c
parentf690808e17925fc45217eb22e8670902ecee5c1b (diff)
[NET]: show bound packet types
Show what protocols are bound to what packet types in /proc/net/ptype Uses kallsyms to decode function pointers if possible. Example: Type Device Function ALL eth1 packet_rcv_spkt+0x0 0800 ip_rcv+0x0 0806 arp_rcv+0x0 86dd :ipv6:ipv6_rcv+0x0 Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 8ddc2ab23142..3af0bdc86491 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2216,6 +2216,135 @@ static const struct file_operations softnet_seq_fops = {
2216 .release = seq_release, 2216 .release = seq_release,
2217}; 2217};
2218 2218
2219static void *ptype_get_idx(loff_t pos)
2220{
2221 struct packet_type *pt = NULL;
2222 loff_t i = 0;
2223 int t;
2224
2225 list_for_each_entry_rcu(pt, &ptype_all, list) {
2226 if (i == pos)
2227 return pt;
2228 ++i;
2229 }
2230
2231 for (t = 0; t < 16; t++) {
2232 list_for_each_entry_rcu(pt, &ptype_base[t], list) {
2233 if (i == pos)
2234 return pt;
2235 ++i;
2236 }
2237 }
2238 return NULL;
2239}
2240
2241static void *ptype_seq_start(struct seq_file *seq, loff_t *pos)
2242{
2243 rcu_read_lock();
2244 return *pos ? ptype_get_idx(*pos - 1) : SEQ_START_TOKEN;
2245}
2246
2247static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2248{
2249 struct packet_type *pt;
2250 struct list_head *nxt;
2251 int hash;
2252
2253 ++*pos;
2254 if (v == SEQ_START_TOKEN)
2255 return ptype_get_idx(0);
2256
2257 pt = v;
2258 nxt = pt->list.next;
2259 if (pt->type == htons(ETH_P_ALL)) {
2260 if (nxt != &ptype_all)
2261 goto found;
2262 hash = 0;
2263 nxt = ptype_base[0].next;
2264 } else
2265 hash = ntohs(pt->type) & 15;
2266
2267 while (nxt == &ptype_base[hash]) {
2268 if (++hash >= 16)
2269 return NULL;
2270 nxt = ptype_base[hash].next;
2271 }
2272found:
2273 return list_entry(nxt, struct packet_type, list);
2274}
2275
2276static void ptype_seq_stop(struct seq_file *seq, void *v)
2277{
2278 rcu_read_unlock();
2279}
2280
2281static void ptype_seq_decode(struct seq_file *seq, void *sym)
2282{
2283#ifdef CONFIG_KALLSYMS
2284 unsigned long offset = 0, symsize;
2285 const char *symname;
2286 char *modname;
2287 char namebuf[128];
2288
2289 symname = kallsyms_lookup((unsigned long)sym, &symsize, &offset,
2290 &modname, namebuf);
2291
2292 if (symname) {
2293 char *delim = ":";
2294
2295 if (!modname)
2296 modname = delim = "";
2297 seq_printf(seq, "%s%s%s%s+0x%lx", delim, modname, delim,
2298 symname, offset);
2299 return;
2300 }
2301#endif
2302
2303 seq_printf(seq, "[%p]", sym);
2304}
2305
2306static int ptype_seq_show(struct seq_file *seq, void *v)
2307{
2308 struct packet_type *pt = v;
2309
2310 if (v == SEQ_START_TOKEN)
2311 seq_puts(seq, "Type Device Function\n");
2312 else {
2313 if (pt->type == htons(ETH_P_ALL))
2314 seq_puts(seq, "ALL ");
2315 else
2316 seq_printf(seq, "%04x", ntohs(pt->type));
2317
2318 seq_printf(seq, " %-8s ",
2319 pt->dev ? pt->dev->name : "");
2320 ptype_seq_decode(seq, pt->func);
2321 seq_putc(seq, '\n');
2322 }
2323
2324 return 0;
2325}
2326
2327static const struct seq_operations ptype_seq_ops = {
2328 .start = ptype_seq_start,
2329 .next = ptype_seq_next,
2330 .stop = ptype_seq_stop,
2331 .show = ptype_seq_show,
2332};
2333
2334static int ptype_seq_open(struct inode *inode, struct file *file)
2335{
2336 return seq_open(file, &ptype_seq_ops);
2337}
2338
2339static const struct file_operations ptype_seq_fops = {
2340 .owner = THIS_MODULE,
2341 .open = ptype_seq_open,
2342 .read = seq_read,
2343 .llseek = seq_lseek,
2344 .release = seq_release,
2345};
2346
2347
2219#ifdef CONFIG_WIRELESS_EXT 2348#ifdef CONFIG_WIRELESS_EXT
2220extern int wireless_proc_init(void); 2349extern int wireless_proc_init(void);
2221#else 2350#else
@@ -2230,6 +2359,9 @@ static int __init dev_proc_init(void)
2230 goto out; 2359 goto out;
2231 if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops)) 2360 if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops))
2232 goto out_dev; 2361 goto out_dev;
2362 if (!proc_net_fops_create("ptype", S_IRUGO, &ptype_seq_fops))
2363 goto out_dev2;
2364
2233 if (wireless_proc_init()) 2365 if (wireless_proc_init())
2234 goto out_softnet; 2366 goto out_softnet;
2235 rc = 0; 2367 rc = 0;
@@ -2237,6 +2369,8 @@ out:
2237 return rc; 2369 return rc;
2238out_softnet: 2370out_softnet:
2239 proc_net_remove("softnet_stat"); 2371 proc_net_remove("softnet_stat");
2372out_dev2:
2373 proc_net_remove("ptype");
2240out_dev: 2374out_dev:
2241 proc_net_remove("dev"); 2375 proc_net_remove("dev");
2242 goto out; 2376 goto out;