Return to xfrmi.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / xfrmi |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2019 Tobias Brunner ! 3: * HSR Hochschule fuer Technik Rapperswil ! 4: * ! 5: * This program is free software; you can redistribute it and/or modify it ! 6: * under the terms of the GNU General Public License as published by the ! 7: * Free Software Foundation; either version 2 of the License, or (at your ! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ! 9: * ! 10: * This program is distributed in the hope that it will be useful, but ! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 13: * for more details. ! 14: */ ! 15: ! 16: #include <stdio.h> ! 17: #include <unistd.h> ! 18: #include <getopt.h> ! 19: #include <errno.h> ! 20: #include <net/if.h> ! 21: #include <linux/netlink.h> ! 22: #include <linux/rtnetlink.h> ! 23: ! 24: #include "kernel_netlink_shared.h" ! 25: ! 26: #ifndef IFLA_XFRM_MAX ! 27: enum { ! 28: IFLA_XFRM_UNSPEC, ! 29: IFLA_XFRM_LINK, ! 30: IFLA_XFRM_IF_ID, ! 31: __IFLA_XFRM_MAX ! 32: }; ! 33: #define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1) ! 34: #endif ! 35: ! 36: /** ! 37: * Create an XFRM interface with the given ID and underlying interface ! 38: */ ! 39: static int add_xfrm_interface(char *name, uint32_t xfrm_id, uint32_t ifindex) ! 40: { ! 41: netlink_buf_t request; ! 42: struct nlmsghdr *hdr; ! 43: struct ifinfomsg *msg; ! 44: struct rtattr *linkinfo, *info_data; ! 45: netlink_socket_t *socket; ! 46: int status = 1; ! 47: ! 48: socket = netlink_socket_create(NETLINK_ROUTE, NULL, FALSE); ! 49: if (!socket) ! 50: { ! 51: return 1; ! 52: } ! 53: ! 54: memset(&request, 0, sizeof(request)); ! 55: ! 56: hdr = &request.hdr; ! 57: hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL; ! 58: hdr->nlmsg_type = RTM_NEWLINK; ! 59: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ! 60: ! 61: msg = NLMSG_DATA(hdr); ! 62: msg->ifi_family = AF_UNSPEC; ! 63: ! 64: netlink_add_attribute(hdr, IFLA_IFNAME, chunk_from_str(name), ! 65: sizeof(request)); ! 66: ! 67: linkinfo = netlink_nested_start(hdr, sizeof(request), IFLA_LINKINFO); ! 68: ! 69: netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk_from_str("xfrm"), ! 70: sizeof(request)); ! 71: ! 72: info_data = netlink_nested_start(hdr, sizeof(request), IFLA_INFO_DATA); ! 73: ! 74: netlink_add_attribute(hdr, IFLA_XFRM_IF_ID, chunk_from_thing(xfrm_id), ! 75: sizeof(request)); ! 76: netlink_add_attribute(hdr, IFLA_XFRM_LINK, chunk_from_thing(ifindex), ! 77: sizeof(request)); ! 78: ! 79: netlink_nested_end(hdr, info_data); ! 80: netlink_nested_end(hdr, linkinfo); ! 81: ! 82: switch (socket->send_ack(socket, hdr)) ! 83: { ! 84: case SUCCESS: ! 85: status = 0; ! 86: break; ! 87: case ALREADY_DONE: ! 88: fprintf(stderr, "XFRM interface already exists\n"); ! 89: break; ! 90: default: ! 91: fprintf(stderr, "failed to create XFRM interface\n"); ! 92: break; ! 93: } ! 94: ! 95: socket->destroy(socket); ! 96: return status; ! 97: } ! 98: ! 99: /** ! 100: * Parse attributes nested in IFLA_INFO_DATA ! 101: */ ! 102: static void parse_info_data(struct rtattr *rta, size_t rtasize, char *phys, ! 103: uint32_t *if_id) ! 104: { ! 105: uint32_t ifindex; ! 106: ! 107: while (RTA_OK(rta, rtasize)) ! 108: { ! 109: switch (rta->rta_type) ! 110: { ! 111: case IFLA_XFRM_IF_ID: ! 112: if (RTA_PAYLOAD(rta) == sizeof(*if_id)) ! 113: { ! 114: *if_id = *(uint32_t*)RTA_DATA(rta); ! 115: } ! 116: break; ! 117: case IFLA_XFRM_LINK: ! 118: if (RTA_PAYLOAD(rta) == sizeof(ifindex)) ! 119: { ! 120: ifindex = *(uint32_t*)RTA_DATA(rta); ! 121: if_indextoname(ifindex, phys); ! 122: } ! 123: break; ! 124: default: ! 125: break; ! 126: } ! 127: rta = RTA_NEXT(rta, rtasize); ! 128: } ! 129: } ! 130: ! 131: /** ! 132: * Parse attributes nested in IFLA_LINKINFO ! 133: */ ! 134: static void parse_linkinfo(struct rtattr *rta, size_t rtasize, char *phys, ! 135: uint32_t *if_id) ! 136: { ! 137: while (RTA_OK(rta, rtasize)) ! 138: { ! 139: switch (rta->rta_type) ! 140: { ! 141: case IFLA_INFO_DATA: ! 142: parse_info_data(RTA_DATA(rta), RTA_PAYLOAD(rta), phys, if_id); ! 143: break; ! 144: default: ! 145: break; ! 146: } ! 147: rta = RTA_NEXT(rta, rtasize); ! 148: } ! 149: } ! 150: ! 151: /** ! 152: * List all installed XFRM interfaces ! 153: */ ! 154: static int list_xfrm_interfaces() ! 155: { ! 156: netlink_buf_t request; ! 157: struct nlmsghdr *hdr, *out, *current; ! 158: struct ifinfomsg *msg; ! 159: struct rtattr *linkinfo; ! 160: netlink_socket_t *socket; ! 161: size_t len; ! 162: int status = 0; ! 163: ! 164: socket = netlink_socket_create(NETLINK_ROUTE, NULL, FALSE); ! 165: if (!socket) ! 166: { ! 167: return 1; ! 168: } ! 169: ! 170: memset(&request, 0, sizeof(request)); ! 171: ! 172: hdr = &request.hdr; ! 173: hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; ! 174: hdr->nlmsg_type = RTM_GETLINK; ! 175: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ! 176: ! 177: msg = NLMSG_DATA(hdr); ! 178: msg->ifi_family = AF_UNSPEC; ! 179: ! 180: linkinfo = netlink_nested_start(hdr, sizeof(request), IFLA_LINKINFO); ! 181: ! 182: netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk_from_str("xfrm"), ! 183: sizeof(request)); ! 184: ! 185: netlink_nested_end(hdr, linkinfo); ! 186: ! 187: if (socket->send(socket, hdr, &out, &len) != SUCCESS) ! 188: { ! 189: return FAILED; ! 190: } ! 191: current = out; ! 192: while (NLMSG_OK(current, len)) ! 193: { ! 194: switch (current->nlmsg_type) ! 195: { ! 196: case NLMSG_DONE: ! 197: break; ! 198: case RTM_NEWLINK: ! 199: msg = NLMSG_DATA(current); ! 200: struct rtattr *rta = IFLA_RTA(msg); ! 201: size_t rtasize = IFLA_PAYLOAD(current); ! 202: char *name = NULL, phys[IF_NAMESIZE] = {}; ! 203: uint32_t if_id = 0; ! 204: ! 205: while (RTA_OK(rta, rtasize)) ! 206: { ! 207: switch (rta->rta_type) ! 208: { ! 209: case IFLA_IFNAME: ! 210: name = RTA_DATA(rta); ! 211: break; ! 212: case IFLA_LINKINFO: ! 213: parse_linkinfo(RTA_DATA(rta), RTA_PAYLOAD(rta), ! 214: phys, &if_id); ! 215: break; ! 216: default: ! 217: break; ! 218: } ! 219: rta = RTA_NEXT(rta, rtasize); ! 220: } ! 221: if (name) ! 222: { ! 223: printf("%2u: %-16s dev %-8s if_id 0x%.8x [%u]\n", ! 224: msg->ifi_index, name, phys, if_id, if_id); ! 225: } ! 226: /* fall through */ ! 227: default: ! 228: current = NLMSG_NEXT(current, len); ! 229: continue; ! 230: } ! 231: break; ! 232: } ! 233: free(out); ! 234: ! 235: socket->destroy(socket); ! 236: return status; ! 237: } ! 238: ! 239: static void usage(FILE *out, char *name) ! 240: { ! 241: fprintf(out, "Create XFRM interfaces\n\n"); ! 242: fprintf(out, "%s [OPTIONS]\n\n", name); ! 243: fprintf(out, "Options:\n"); ! 244: fprintf(out, " -h, --help print this help.\n"); ! 245: fprintf(out, " -v, --debug set debug level, default: 1.\n"); ! 246: fprintf(out, " -l, --list list XFRM interfaces.\n"); ! 247: fprintf(out, " -n, --name=NAME name of the XFRM interface.\n"); ! 248: fprintf(out, " -i, --id=ID optional numeric XFRM ID.\n"); ! 249: fprintf(out, " -d, --dev=DEVICE underlying physical interface.\n"); ! 250: fprintf(out, "\n"); ! 251: } ! 252: ! 253: int main(int argc, char *argv[]) ! 254: { ! 255: char *name = NULL, *dev = NULL, *end; ! 256: uint32_t xfrm_id = 0; ! 257: u_int ifindex; ! 258: ! 259: library_init(NULL, "xfrmi"); ! 260: atexit(library_deinit); ! 261: ! 262: while (true) ! 263: { ! 264: struct option long_opts[] = { ! 265: {"help", no_argument, NULL, 'h' }, ! 266: {"debug", no_argument, NULL, 'v' }, ! 267: {"list", no_argument, NULL, 'l' }, ! 268: {"name", required_argument, NULL, 'n' }, ! 269: {"id", required_argument, NULL, 'i' }, ! 270: {"dev", required_argument, NULL, 'd' }, ! 271: {0,0,0,0 }, ! 272: }; ! 273: switch (getopt_long(argc, argv, "hvln:i:d:", long_opts, NULL)) ! 274: { ! 275: case EOF: ! 276: break; ! 277: case 'h': ! 278: usage(stdout, argv[0]); ! 279: return 0; ! 280: case 'l': ! 281: list_xfrm_interfaces(); ! 282: return 0; ! 283: case 'v': ! 284: dbg_default_set_level(atoi(optarg)); ! 285: continue; ! 286: case 'n': ! 287: name = optarg; ! 288: continue; ! 289: case 'i': ! 290: errno = 0; ! 291: xfrm_id = strtoul(optarg, &end, 0); ! 292: if (errno || *end) ! 293: { ! 294: fprintf(stderr, "invalid XFRM ID: %s\n", ! 295: errno ? strerror(errno) : end); ! 296: return 1; ! 297: } ! 298: continue; ! 299: case 'd': ! 300: dev = optarg; ! 301: continue; ! 302: default: ! 303: usage(stderr, argv[0]); ! 304: return 1; ! 305: } ! 306: break; ! 307: } ! 308: ! 309: if (!name || !dev) ! 310: { ! 311: fprintf(stderr, "please specify a name and a physical interface\n"); ! 312: return 1; ! 313: } ! 314: ifindex = if_nametoindex(dev); ! 315: if (!ifindex) ! 316: { ! 317: fprintf(stderr, "physical interface %s not found\n", dev); ! 318: return 1; ! 319: } ! 320: ! 321: return add_xfrm_interface(name, xfrm_id, ifindex); ! 322: }