File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / xfrmi / xfrmi.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:44 2020 UTC (4 years, 4 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    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>