1/* 2 * ll_map.c 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10 * 11 */ 12 13#include <stdio.h> 14#include <stdlib.h> 15#include <unistd.h> 16#include <syslog.h> 17#include <fcntl.h> 18#include <sys/socket.h> 19#include <netinet/in.h> 20#include <net/if.h> 21#include <string.h> 22#if (defined CONFIG_KERNEL_2_6_36) 23#define IPROUTE2 24#include "utils.h" 25#endif 26#include "libnetlink.h" 27#include "ll_map.h" 28 29struct idxmap 30{ 31 struct idxmap * next; 32 unsigned index; 33 int type; 34 int alen; 35 unsigned flags; 36 unsigned char addr[8]; 37 char name[16]; 38}; 39 40static struct idxmap *idxmap[16]; 41 42int ll_remember_index(const struct sockaddr_nl *who, 43 struct nlmsghdr *n, void *arg) 44{ 45 int h; 46 struct ifinfomsg *ifi = NLMSG_DATA(n); 47 struct idxmap *im, **imp; 48 struct rtattr *tb[IFLA_MAX+1]; 49 50 if (n->nlmsg_type != RTM_NEWLINK) 51 return 0; 52 53 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi))) 54 return -1; 55 56 57 memset(tb, 0, sizeof(tb)); 58 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); 59 if (tb[IFLA_IFNAME] == NULL) 60 return 0; 61 62 h = ifi->ifi_index&0xF; 63 64 for (imp=&idxmap[h]; (im=*imp)!=NULL; imp = &im->next) 65 if (im->index == ifi->ifi_index) 66 break; 67 68 if (im == NULL) { 69 im = malloc(sizeof(*im)); 70 if (im == NULL) 71 return 0; 72 im->next = *imp; 73 im->index = ifi->ifi_index; 74 *imp = im; 75 } 76 77 im->type = ifi->ifi_type; 78 im->flags = ifi->ifi_flags; 79 if (tb[IFLA_ADDRESS]) { 80 int alen; 81 im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]); 82 if (alen > sizeof(im->addr)) 83 alen = sizeof(im->addr); 84 memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen); 85 } else { 86 im->alen = 0; 87 memset(im->addr, 0, sizeof(im->addr)); 88 } 89 strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME])); 90 return 0; 91} 92 93const char *ll_idx_n2a(unsigned idx, char *buf) 94{ 95 struct idxmap *im; 96 97 if (idx == 0) 98 return "*"; 99 for (im = idxmap[idx&0xF]; im; im = im->next) 100 if (im->index == idx) 101 return im->name; 102 snprintf(buf, 16, "if%d", idx); 103 return buf; 104} 105 106 107const char *ll_index_to_name(unsigned idx) 108{ 109 static char nbuf[16]; 110 111 return ll_idx_n2a(idx, nbuf); 112} 113 114int ll_index_to_type(unsigned idx) 115{ 116 struct idxmap *im; 117 118 if (idx == 0) 119 return -1; 120 for (im = idxmap[idx&0xF]; im; im = im->next) 121 if (im->index == idx) 122 return im->type; 123 return -1; 124} 125 126unsigned ll_index_to_flags(unsigned idx) 127{ 128 struct idxmap *im; 129 130 if (idx == 0) 131 return 0; 132 133 for (im = idxmap[idx&0xF]; im; im = im->next) 134 if (im->index == idx) 135 return im->flags; 136 return 0; 137} 138 139unsigned ll_name_to_index(const char *name) 140{ 141 static char ncache[16]; 142 static int icache; 143 struct idxmap *im; 144 int i; 145 146 if (name == NULL) 147 return 0; 148 if (icache && strcmp(name, ncache) == 0) 149 return icache; 150 for (i=0; i<16; i++) { 151 for (im = idxmap[i]; im; im = im->next) { 152 if (strcmp(im->name, name) == 0) { 153 icache = im->index; 154 strcpy(ncache, name); 155 return im->index; 156 } 157 } 158 } 159 160 return if_nametoindex(name); 161} 162 163int ll_init_map(struct rtnl_handle *rth) 164{ 165 if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) { 166 perror("Cannot send dump request"); 167 exit(1); 168 } 169 170 if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) { 171 fprintf(stderr, "Dump terminated\n"); 172 exit(1); 173 } 174 return 0; 175} 176