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>