Annotation of embedaddon/strongswan/src/xfrmi/xfrmi.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>