return status;
}
+/**
+ * Parse attributes nested in IFLA_INFO_DATA
+ */
+static void parse_info_data(struct rtattr *rta, size_t rtasize, char *phys,
+ uint32_t *if_id)
+{
+ uint32_t ifindex;
+
+ while (RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case IFLA_XFRM_IF_ID:
+ if (RTA_PAYLOAD(rta) == sizeof(*if_id))
+ {
+ *if_id = *(uint32_t*)RTA_DATA(rta);
+ }
+ break;
+ case IFLA_XFRM_LINK:
+ if (RTA_PAYLOAD(rta) == sizeof(ifindex))
+ {
+ ifindex = *(uint32_t*)RTA_DATA(rta);
+ if_indextoname(ifindex, phys);
+ }
+ break;
+ default:
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+}
+
+/**
+ * Parse attributes nested in IFLA_LINKINFO
+ */
+static void parse_linkinfo(struct rtattr *rta, size_t rtasize, char *phys,
+ uint32_t *if_id)
+{
+ while (RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case IFLA_INFO_DATA:
+ parse_info_data(RTA_DATA(rta), RTA_PAYLOAD(rta), phys, if_id);
+ break;
+ default:
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+}
+
+/**
+ * List all installed XFRM interfaces
+ */
+static int list_xfrm_interfaces()
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr, *out, *current;
+ struct ifinfomsg *msg;
+ struct rtattr *linkinfo;
+ netlink_socket_t *socket;
+ size_t len;
+ int status = 0;
+
+ socket = netlink_socket_create(NETLINK_ROUTE, NULL, FALSE);
+ if (!socket)
+ {
+ return 1;
+ }
+
+ memset(&request, 0, sizeof(request));
+
+ hdr = &request.hdr;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ hdr->nlmsg_type = RTM_GETLINK;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+
+ msg = NLMSG_DATA(hdr);
+ msg->ifi_family = AF_UNSPEC;
+
+ /* the following attributes are nested under this one */
+ linkinfo = netlink_reserve(hdr, sizeof(request), IFLA_LINKINFO, 0);
+ linkinfo = (void*)linkinfo - RTA_LENGTH(0);
+
+ netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk_from_str("xfrm"),
+ sizeof(request));
+
+ linkinfo->rta_len = NLMSG_TAIL(hdr) - (void*)linkinfo;
+
+ if (socket->send(socket, hdr, &out, &len) != SUCCESS)
+ {
+ return FAILED;
+ }
+ current = out;
+ while (NLMSG_OK(current, len))
+ {
+ switch (current->nlmsg_type)
+ {
+ case NLMSG_DONE:
+ break;
+ case RTM_NEWLINK:
+ msg = NLMSG_DATA(current);
+ struct rtattr *rta = IFLA_RTA(msg);
+ size_t rtasize = IFLA_PAYLOAD(current);
+ char *name = NULL, phys[IF_NAMESIZE] = {};
+ uint32_t if_id = 0;
+
+ while (RTA_OK(rta, rtasize))
+ {
+ switch (rta->rta_type)
+ {
+ case IFLA_IFNAME:
+ name = RTA_DATA(rta);
+ break;
+ case IFLA_LINKINFO:
+ parse_linkinfo(RTA_DATA(rta), RTA_PAYLOAD(rta),
+ phys, &if_id);
+ break;
+ default:
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+ if (name)
+ {
+ printf("%2u: %-16s dev %-8s if_id 0x%.8x [%u]\n",
+ msg->ifi_index, name, phys, if_id, if_id);
+ }
+ /* fall through */
+ default:
+ current = NLMSG_NEXT(current, len);
+ continue;
+ }
+ break;
+ }
+ free(out);
+
+ socket->destroy(socket);
+ return status;
+}
+
static void usage(FILE *out, char *name)
{
fprintf(out, "Create XFRM interfaces\n\n");
fprintf(out, "Options:\n");
fprintf(out, " -h, --help print this help.\n");
fprintf(out, " -v, --debug set debug level, default: 1.\n");
+ fprintf(out, " -l, --list list XFRM interfaces.\n");
fprintf(out, " -n, --name=NAME name of the XFRM interface.\n");
fprintf(out, " -i, --id=ID optional numeric XFRM ID.\n");
fprintf(out, " -d, --dev=DEVICE underlying physical interface.\n");
uint32_t xfrm_id = 0;
u_int ifindex;
+ library_init(NULL, "xfrmi");
+ atexit(library_deinit);
+
while (true)
{
struct option long_opts[] = {
{"help", no_argument, NULL, 'h' },
{"debug", no_argument, NULL, 'v' },
+ {"list", no_argument, NULL, 'l' },
{"name", required_argument, NULL, 'n' },
{"id", required_argument, NULL, 'i' },
{"dev", required_argument, NULL, 'd' },
{0,0,0,0 },
};
- switch (getopt_long(argc, argv, "hvn:i:d:", long_opts, NULL))
+ switch (getopt_long(argc, argv, "hvln:i:d:", long_opts, NULL))
{
case EOF:
break;
case 'h':
usage(stdout, argv[0]);
return 0;
+ case 'l':
+ list_xfrm_interfaces();
+ return 0;
case 'v':
dbg_default_set_level(atoi(optarg));
continue;
return 1;
}
- library_init(NULL, "xfrmi");
- atexit(library_deinit);
-
return add_xfrm_interface(name, xfrm_id, ifindex);
}