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