iproute2/lib/ll_map.c
Stephen Hemminger cd70f3f522 libnetlink: remove unused junk callback
Both rtnl_talk and rtnl_dump had a callback for handling portions
of netlink message that do not match the correct pid or seq.
But this callback was never used by any part of iproute2 so remove
it.
2011-12-28 10:37:12 -08:00

216 lines
4.1 KiB
C

/*
* ll_map.c
*
* 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.
*
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <linux/if.h>
#include "libnetlink.h"
#include "ll_map.h"
extern unsigned int if_nametoindex (const char *);
struct ll_cache
{
struct ll_cache *idx_next;
unsigned flags;
int index;
unsigned short type;
unsigned short alen;
char name[IFNAMSIZ];
unsigned char addr[20];
};
#define IDXMAP_SIZE 1024
static struct ll_cache *idx_head[IDXMAP_SIZE];
static inline struct ll_cache *idxhead(int idx)
{
return idx_head[idx & (IDXMAP_SIZE - 1)];
}
int ll_remember_index(const struct sockaddr_nl *who,
struct nlmsghdr *n, void *arg)
{
int h;
struct ifinfomsg *ifi = NLMSG_DATA(n);
struct ll_cache *im, **imp;
struct rtattr *tb[IFLA_MAX+1];
if (n->nlmsg_type != RTM_NEWLINK)
return 0;
if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))
return -1;
memset(tb, 0, sizeof(tb));
parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));
if (tb[IFLA_IFNAME] == NULL)
return 0;
h = ifi->ifi_index & (IDXMAP_SIZE - 1);
for (imp = &idx_head[h]; (im=*imp)!=NULL; imp = &im->idx_next)
if (im->index == ifi->ifi_index)
break;
if (im == NULL) {
im = malloc(sizeof(*im));
if (im == NULL)
return 0;
im->idx_next = *imp;
im->index = ifi->ifi_index;
*imp = im;
}
im->type = ifi->ifi_type;
im->flags = ifi->ifi_flags;
if (tb[IFLA_ADDRESS]) {
int alen;
im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
if (alen > sizeof(im->addr))
alen = sizeof(im->addr);
memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen);
} else {
im->alen = 0;
memset(im->addr, 0, sizeof(im->addr));
}
strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]));
return 0;
}
const char *ll_idx_n2a(unsigned idx, char *buf)
{
const struct ll_cache *im;
if (idx == 0)
return "*";
for (im = idxhead(idx); im; im = im->idx_next)
if (im->index == idx)
return im->name;
snprintf(buf, IFNAMSIZ, "if%d", idx);
return buf;
}
const char *ll_index_to_name(unsigned idx)
{
static char nbuf[IFNAMSIZ];
return ll_idx_n2a(idx, nbuf);
}
int ll_index_to_type(unsigned idx)
{
const struct ll_cache *im;
if (idx == 0)
return -1;
for (im = idxhead(idx); im; im = im->idx_next)
if (im->index == idx)
return im->type;
return -1;
}
unsigned ll_index_to_flags(unsigned idx)
{
const struct ll_cache *im;
if (idx == 0)
return 0;
for (im = idxhead(idx); im; im = im->idx_next)
if (im->index == idx)
return im->flags;
return 0;
}
unsigned ll_index_to_addr(unsigned idx, unsigned char *addr,
unsigned alen)
{
const struct ll_cache *im;
if (idx == 0)
return 0;
for (im = idxhead(idx); im; im = im->idx_next) {
if (im->index == idx) {
if (alen > sizeof(im->addr))
alen = sizeof(im->addr);
if (alen > im->alen)
alen = im->alen;
memcpy(addr, im->addr, alen);
return alen;
}
}
return 0;
}
unsigned ll_name_to_index(const char *name)
{
static char ncache[IFNAMSIZ];
static int icache;
struct ll_cache *im;
int i;
unsigned idx;
if (name == NULL)
return 0;
if (icache && strcmp(name, ncache) == 0)
return icache;
for (i=0; i<IDXMAP_SIZE; i++) {
for (im = idx_head[i]; im; im = im->idx_next) {
if (strcmp(im->name, name) == 0) {
icache = im->index;
strcpy(ncache, name);
return im->index;
}
}
}
idx = if_nametoindex(name);
if (idx == 0)
sscanf(name, "if%u", &idx);
return idx;
}
int ll_init_map(struct rtnl_handle *rth)
{
static int initialized;
if (initialized)
return 0;
if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {
perror("Cannot send dump request");
exit(1);
}
if (rtnl_dump_filter(rth, ll_remember_index, NULL) < 0) {
fprintf(stderr, "Dump terminated\n");
exit(1);
}
initialized = 1;
return 0;
}