iproute2/ip/link_vti.c
<<
>>
Prefs
   1/*
   2 * link_vti.c   VTI driver module
   3 *
   4 *              This program is free software; you can redistribute it and/or
   5 *              modify it under the terms of the GNU General Public License
   6 *              as published by the Free Software Foundation; either version
   7 *              2 of the License, or (at your option) any later version.
   8 *
   9 * Authors:     Herbert Xu <herbert@gondor.apana.org.au>
  10 *          Saurabh Mohan <saurabh.mohan@vyatta.com> Modified link_gre.c for VTI
  11 */
  12
  13#include <string.h>
  14#include <net/if.h>
  15#include <sys/types.h>
  16#include <sys/socket.h>
  17#include <arpa/inet.h>
  18
  19#include <linux/ip.h>
  20#include <linux/if_tunnel.h>
  21#include "rt_names.h"
  22#include "utils.h"
  23#include "ip_common.h"
  24#include "tunnel.h"
  25
  26static void vti_print_help(struct link_util *lu, int argc, char **argv, FILE *f)
  27{
  28        fprintf(f,
  29                "Usage: ... %-4s        [ remote ADDR ]\n"
  30                "               [ local ADDR ]\n"
  31                "               [ [i|o]key KEY ]\n"
  32                "               [ dev PHYS_DEV ]\n"
  33                "               [ fwmark MARK ]\n"
  34                "\n"
  35                "Where: ADDR := { IP_ADDRESS }\n"
  36                "       KEY  := { DOTTED_QUAD | NUMBER }\n"
  37                "       MARK := { 0x0..0xffffffff }\n",
  38                lu->id);
  39}
  40
  41static int vti_parse_opt(struct link_util *lu, int argc, char **argv,
  42                         struct nlmsghdr *n)
  43{
  44        struct ifinfomsg *ifi = NLMSG_DATA(n);
  45        struct {
  46                struct nlmsghdr n;
  47                struct ifinfomsg i;
  48        } req = {
  49                .n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
  50                .n.nlmsg_flags = NLM_F_REQUEST,
  51                .n.nlmsg_type = RTM_GETLINK,
  52                .i.ifi_family = preferred_family,
  53                .i.ifi_index = ifi->ifi_index,
  54        };
  55        struct nlmsghdr *answer;
  56        struct rtattr *tb[IFLA_MAX + 1];
  57        struct rtattr *linkinfo[IFLA_INFO_MAX+1];
  58        struct rtattr *vtiinfo[IFLA_VTI_MAX + 1];
  59        __be32 ikey = 0;
  60        __be32 okey = 0;
  61        inet_prefix saddr, daddr;
  62        unsigned int link = 0;
  63        __u32 fwmark = 0;
  64        int len;
  65
  66        inet_prefix_reset(&saddr);
  67        inet_prefix_reset(&daddr);
  68
  69        if (!(n->nlmsg_flags & NLM_F_CREATE)) {
  70                const struct rtattr *rta;
  71
  72                if (rtnl_talk(&rth, &req.n, &answer) < 0) {
  73get_failed:
  74                        fprintf(stderr,
  75                                "Failed to get existing tunnel info.\n");
  76                        return -1;
  77                }
  78
  79                len = answer->nlmsg_len;
  80                len -= NLMSG_LENGTH(sizeof(*ifi));
  81                if (len < 0)
  82                        goto get_failed;
  83
  84                parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
  85
  86                if (!tb[IFLA_LINKINFO])
  87                        goto get_failed;
  88
  89                parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
  90
  91                if (!linkinfo[IFLA_INFO_DATA])
  92                        goto get_failed;
  93
  94                parse_rtattr_nested(vtiinfo, IFLA_VTI_MAX,
  95                                    linkinfo[IFLA_INFO_DATA]);
  96
  97                rta = vtiinfo[IFLA_VTI_LOCAL];
  98                if (rta && get_addr_rta(&saddr, rta, AF_INET))
  99                        goto get_failed;
 100
 101                rta = vtiinfo[IFLA_VTI_REMOTE];
 102                if (rta && get_addr_rta(&daddr, rta, AF_INET))
 103                        goto get_failed;
 104
 105                if (vtiinfo[IFLA_VTI_IKEY])
 106                        ikey = rta_getattr_u32(vtiinfo[IFLA_VTI_IKEY]);
 107
 108                if (vtiinfo[IFLA_VTI_OKEY])
 109                        okey = rta_getattr_u32(vtiinfo[IFLA_VTI_OKEY]);
 110
 111                if (vtiinfo[IFLA_VTI_LINK])
 112                        link = rta_getattr_u8(vtiinfo[IFLA_VTI_LINK]);
 113
 114                if (vtiinfo[IFLA_VTI_FWMARK])
 115                        fwmark = rta_getattr_u32(vtiinfo[IFLA_VTI_FWMARK]);
 116
 117                free(answer);
 118        }
 119
 120        while (argc > 0) {
 121                if (!matches(*argv, "key")) {
 122                        NEXT_ARG();
 123                        ikey = okey = tnl_parse_key("key", *argv);
 124                } else if (!matches(*argv, "ikey")) {
 125                        NEXT_ARG();
 126                        ikey = tnl_parse_key("ikey", *argv);
 127                } else if (!matches(*argv, "okey")) {
 128                        NEXT_ARG();
 129                        okey = tnl_parse_key("okey", *argv);
 130                } else if (!matches(*argv, "remote")) {
 131                        NEXT_ARG();
 132                        get_addr(&daddr, *argv, AF_INET);
 133                } else if (!matches(*argv, "local")) {
 134                        NEXT_ARG();
 135                        get_addr(&saddr, *argv, AF_INET);
 136                } else if (!matches(*argv, "dev")) {
 137                        NEXT_ARG();
 138                        link = ll_name_to_index(*argv);
 139                        if (!link)
 140                                exit(nodev(*argv));
 141                } else if (strcmp(*argv, "fwmark") == 0) {
 142                        NEXT_ARG();
 143                        if (get_u32(&fwmark, *argv, 0))
 144                                invarg("invalid fwmark\n", *argv);
 145                } else {
 146                        vti_print_help(lu, argc, argv, stderr);
 147                        return -1;
 148                }
 149                argc--; argv++;
 150        }
 151
 152        addattr32(n, 1024, IFLA_VTI_IKEY, ikey);
 153        addattr32(n, 1024, IFLA_VTI_OKEY, okey);
 154        if (is_addrtype_inet_not_unspec(&saddr))
 155                addattr_l(n, 1024, IFLA_VTI_LOCAL, saddr.data, saddr.bytelen);
 156        if (is_addrtype_inet_not_unspec(&daddr))
 157                addattr_l(n, 1024, IFLA_VTI_REMOTE, daddr.data, daddr.bytelen);
 158        addattr32(n, 1024, IFLA_VTI_FWMARK, fwmark);
 159        if (link)
 160                addattr32(n, 1024, IFLA_VTI_LINK, link);
 161
 162        return 0;
 163}
 164
 165static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 166{
 167        char s2[64];
 168
 169        if (!tb)
 170                return;
 171
 172        tnl_print_endpoint("remote", tb[IFLA_VTI_REMOTE], AF_INET);
 173        tnl_print_endpoint("local", tb[IFLA_VTI_LOCAL], AF_INET);
 174
 175        if (tb[IFLA_VTI_LINK]) {
 176                __u32 link = rta_getattr_u32(tb[IFLA_VTI_LINK]);
 177
 178                if (link) {
 179                        print_string(PRINT_ANY, "link", "dev %s ",
 180                                     ll_index_to_name(link));
 181                }
 182        }
 183
 184        if (tb[IFLA_VTI_IKEY]) {
 185                struct rtattr *rta = tb[IFLA_VTI_IKEY];
 186                __u32 key = rta_getattr_u32(rta);
 187
 188                if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
 189                        print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
 190        }
 191
 192        if (tb[IFLA_VTI_OKEY]) {
 193                struct rtattr *rta = tb[IFLA_VTI_OKEY];
 194                __u32 key = rta_getattr_u32(rta);
 195
 196                if (key && inet_ntop(AF_INET, RTA_DATA(rta), s2, sizeof(s2)))
 197                        print_string(PRINT_ANY, "okey", "okey %s ", s2);
 198        }
 199
 200        if (tb[IFLA_VTI_FWMARK]) {
 201                __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
 202
 203                if (fwmark) {
 204                        print_0xhex(PRINT_ANY,
 205                                    "fwmark", "fwmark %#llx ", fwmark);
 206                }
 207        }
 208}
 209
 210struct link_util vti_link_util = {
 211        .id = "vti",
 212        .maxattr = IFLA_VTI_MAX,
 213        .parse_opt = vti_parse_opt,
 214        .print_opt = vti_print_opt,
 215        .print_help = vti_print_help,
 216};
 217