Annotation of embedaddon/strongswan/src/xfrmi/xfrmi.c, revision 1.1.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>