diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/if_index.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/if_index.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c new file mode 100644 index 0000000..3f5a890 --- /dev/null +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -0,0 +1,140 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <net/if.h> + +#define IF_INET6_FILENAME "/proc/net/if_inet6" + +/* /proc/net/if_inet6 contains lines that look like this: + * + * fe8000000000000000000000836fc168 0b 00 20 80 sit7 + * + * | | | | | | + * address --' | | | | | + * index --------' | | | | + * prefix length ---' | | | + * scope --------------' | | + * flags -----------------' | + * name -------------------------' + * + */ + +static int get_one_interface(FILE *fd, char *interface, int iflen, unsigned int *index) +{ + char buffer[80]; + static char seps[] = " \012"; + char *c = buffer; + char *sp; + if (!fgets(buffer, 80, fd)) + return 1; + if (strtok_r(buffer, seps, &sp) == NULL) return 1; + if (c = strtok_r(NULL, seps, &sp), c == NULL) return 1; + *index = strtoul(c, NULL, 16); + if (strtok_r(NULL, seps, &sp) == NULL) return 1; + if (strtok_r(NULL, seps, &sp) == NULL) return 1; + if (strtok_r(NULL, seps, &sp) == NULL) return 1; + if (c = strtok_r(NULL, seps, &sp), c == NULL) return 1; + strncpy(interface, c, iflen); + return 0; +} + +unsigned int if_nametoindex(const char *ifname) +{ + FILE *fd = fopen(IF_INET6_FILENAME, "r"); + char this_ifname[IFNAMSIZ]; + unsigned int this_index; + if (!fd) return 0; + while (get_one_interface(fd, this_ifname, IFNAMSIZ, &this_index) == 0) { + if (!strcmp(this_ifname, ifname)) { + fclose(fd); + return this_index; + } + } + fclose(fd); + return 0; +} + +char *if_indextoname(unsigned int ifindex, char *ifname) +{ + FILE *fd = fopen(IF_INET6_FILENAME, "r"); + unsigned int this_index; + if (!fd) return NULL; + while (get_one_interface(fd, ifname, IFNAMSIZ, &this_index) == 0) { + if (this_index == ifindex) { + fclose(fd); + return ifname; + } + } + fclose(fd); + return NULL; +} + +void if_freenameindex(struct if_nameindex *ifn) +{ + struct if_nameindex *ptr = ifn; + while (ptr->if_name || ptr->if_index) + { + if (ptr->if_name) + free(ptr->if_name); + ptr++; + } + free(ifn); +} + +struct if_nameindex *if_nameindex(void) +{ + FILE *fd = fopen(IF_INET6_FILENAME, "r"); + struct if_nameindex *ifn = NULL; + int nifs = 0; + if (!fd) return NULL; + do + { + struct if_nameindex *newifn; + nifs++; + newifn = realloc(ifn, nifs*sizeof(struct if_nameindex)); + if (!newifn) + { + /* We ran out of memory. */ + if (--nifs) + { + free(ifn[nifs-1].if_name); + ifn[nifs-1].if_name = 0; + ifn[nifs-1].if_index = 0; + if_freenameindex(ifn); + } + return NULL; + } + ifn = newifn; + ifn[nifs-1].if_index = 0; + ifn[nifs-1].if_name = malloc(IFNAMSIZ); + if (ifn[nifs-1].if_name == NULL) + { + if_freenameindex(ifn); + return NULL; + } + } + while (get_one_interface(fd, ifn[nifs-1].if_name, IFNAMSIZ, + &ifn[nifs-1].if_index) == 0); + free(ifn[nifs-1].if_name); + ifn[nifs-1].if_name = NULL; + fclose(fd); + return ifn; +} |