#define _GNU_SOURCE #include #include #include #include #include #include #include "__netlink.h" struct ifnamemap { unsigned int index; unsigned char namelen; char name[IFNAMSIZ]; }; struct ifnameindexctx { unsigned int num; unsigned int str_bytes; struct ifnamemap *list; }; static int __handle_link(void *pctx, struct nlmsghdr *h) { struct ifnameindexctx *ctx = pctx; struct ifinfomsg *ifim = NLMSG_DATA(h); struct rtattr *rta; struct ifnamemap *e; for (rta = NLMSG_RTA(h, sizeof(*ifim)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) { if (rta->rta_type != IFLA_IFNAME) continue; if (RTA_DATALEN(rta) > IFNAMSIZ) return -ENOBUFS; ctx->num++; ctx->str_bytes += RTA_DATALEN(rta) + 1; e = realloc(ctx->list, sizeof(struct ifnamemap[ctx->num])); if (e == 0) return -ENOMEM; ctx->list = e; e = &ctx->list[ctx->num-1]; e->index = ifim->ifi_index; e->namelen = RTA_DATALEN(rta); memcpy(e->name, RTA_DATA(rta), IFNAMSIZ); } return 0; } struct if_nameindex *if_nameindex() { struct ifnameindexctx _ctx, *ctx = &_ctx; struct if_nameindex *ifs = NULL; struct __netlink_handle *nh; int r, i; char *p; nh = __netlink_open(NETLINK_ROUTE); if (!nh) goto err; memset(ctx, 0, sizeof(*ctx)); r = __netlink_enumerate(nh, RTM_GETLINK, __handle_link, ctx); __netlink_close(nh); if (r < 0) goto err; ifs = malloc(sizeof(struct if_nameindex[ctx->num+1]) + ctx->str_bytes); if (ifs == 0) goto err; p = (char*)ifs + sizeof(struct if_nameindex[ctx->num+1]); for (i = 0; i < ctx->num; i++) { ifs[i].if_index = ctx->list[i].index; ifs[i].if_name = p; memcpy(p, ctx->list[i].name, ctx->list[i].namelen); p += ctx->list[i].namelen; *p++ = 0; } ifs[i].if_index = 0; ifs[i].if_name = 0; err: free(ctx->list); if (ifs == NULL) errno = ENOBUFS; return ifs; }