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 <string.h> 21 22#include "libnetlink.h" 23#include "ll_map.h" 24 25extern unsigned int if_nametoindex (const char *); 26 27struct idxmap 28{ 29 struct idxmap * next; 30 unsigned index; 31 int type; 32 int alen; 33 unsigned flags; 34 unsigned char addr[20]; 35 char name[16]; 36}; 37 38static struct idxmap *idxmap[16]; 39 40int ll_remember_index(const struct sockaddr_nl *who, 41 struct nlmsghdr *n, void *arg) 42{ 43 int h; 44 struct ifinfomsg *ifi = NLMSG_DATA(n); 45 struct idxmap *im, **imp; 46 struct rtattr *tb[IFLA_MAX+1]; 47 48 if (n->nlmsg_type != RTM_NEWLINK) 49 return 0; 50 51 if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi))) 52 return -1; 53 54 55 memset(tb, 0, sizeof(tb)); 56 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); 57 if (tb[IFLA_IFNAME] == NULL) 58 return 0; 59 60 h = ifi->ifi_index&0xF; 61 62 for (imp=&idxmap[h]; (im=*imp)!=NULL; imp = &im->next) 63 if (im->index == ifi->ifi_index) 64 break; 65 66 if (im == NULL) { 67 im = malloc(sizeof(*im)); 68 if (im == NULL) 69 return 0; 70 im->next = *imp; 71 im->index = ifi->ifi_index; 72 *imp = im; 73 } 74 75 im->type = ifi->ifi_type; 76 im->flags = ifi->ifi_flags; 77 if (tb[IFLA_ADDRESS]) { 78 int alen; 79 im->alen = alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]); 80 if (alen > sizeof(im->addr)) 81 alen = sizeof(im->addr); 82 memcpy(im->addr, RTA_DATA(tb[IFLA_ADDRESS]), alen); 83 } else { 84 im->alen = 0; 85 memset(im->addr, 0, sizeof(im->addr)); 86 } 87 strcpy(im->name, RTA_DATA(tb[IFLA_IFNAME])); 88 return 0; 89} 90 91const char *ll_idx_n2a(unsigned idx, char *buf) 92{ 93 struct idxmap *im; 94 95 if (idx == 0) 96 return "*"; 97 for (im = idxmap[idx&0xF]; im; im = im->next) 98 if (im->index == idx) 99 return im->name; 100 snprintf(buf, 16, "if%d", idx); 101 return buf; 102} 103 104 105const char *ll_index_to_name(unsigned idx) 106{ 107 static char nbuf[16]; 108 109 return ll_idx_n2a(idx, nbuf); 110} 111 112int ll_index_to_type(unsigned idx) 113{ 114 struct idxmap *im; 115 116 if (idx == 0) 117 return -1; 118 for (im = idxmap[idx&0xF]; im; im = im->next) 119 if (im->index == idx) 120 return im->type; 121 return -1; 122} 123 124unsigned ll_index_to_flags(unsigned idx) 125{ 126 struct idxmap *im; 127 128 if (idx == 0) 129 return 0; 130 131 for (im = idxmap[idx&0xF]; im; im = im->next) 132 if (im->index == idx) 133 return im->flags; 134 return 0; 135} 136 137unsigned ll_index_to_addr(unsigned idx, unsigned char *addr, 138 unsigned alen) 139{ 140 struct idxmap *im; 141 142 if (idx == 0) 143 return 0; 144 145 for (im = idxmap[idx&0xF]; im; im = im->next) { 146 if (im->index == idx) { 147 if (alen > sizeof(im->addr)) 148 alen = sizeof(im->addr); 149 if (alen > im->alen) 150 alen = im->alen; 151 memcpy(addr, im->addr, alen); 152 return alen; 153 } 154 } 155 return 0; 156} 157 158unsigned ll_name_to_index(const char *name) 159{ 160 static char ncache[16]; 161 static int icache; 162 struct idxmap *im; 163 int i; 164 unsigned idx; 165 166 if (name == NULL) 167 return 0; 168 if (icache && strcmp(name, ncache) == 0) 169 return icache; 170 for (i=0; i<16; i++) { 171 for (im = idxmap[i]; im; im = im->next) { 172 if (strcmp(im->name, name) == 0) { 173 icache = im->index; 174 strcpy(ncache, name); 175 return im->index; 176 } 177 } 178 } 179 180 idx = if_nametoindex(name); 181 if (idx == 0) 182 sscanf(name, "if%u", &idx); 183 return idx; 184} 185 186int ll_init_map(struct rtnl_handle *rth) 187{ 188 if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) { 189 perror("Cannot send dump request"); 190 exit(1); 191 } 192 193 if (rtnl_dump_filter(rth, ll_remember_index, &idxmap, NULL, NULL) < 0) { 194 fprintf(stderr, "Dump terminated\n"); 195 exit(1); 196 } 197 return 0; 198} 199