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