]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/iptoken.c
libnetlink: add size argument to rtnl_talk
[mirror_iproute2.git] / ip / iptoken.c
CommitLineData
191b60bd
DB
1/*
2 * iptoken.c "ip token"
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: Daniel Borkmann, <borkmann@redhat.com>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <stdbool.h>
15#include <unistd.h>
16#include <syslog.h>
17#include <fcntl.h>
18#include <string.h>
19#include <sys/socket.h>
20#include <netinet/in.h>
21#include <netinet/ip.h>
22#include <arpa/inet.h>
23#include <linux/types.h>
24#include <linux/if.h>
25
26#include "rt_names.h"
27#include "utils.h"
28#include "ip_common.h"
29
30extern struct rtnl_handle rth;
31
32struct rtnl_dump_args {
33 FILE *fp;
34 int ifindex;
35};
36
37static void usage(void) __attribute__((noreturn));
38
39static void usage(void)
40{
41 fprintf(stderr, "Usage: ip token [ list | set | get ] [ TOKEN ] [ dev DEV ]\n");
42 exit(-1);
43}
44
45static int print_token(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
46{
47 struct rtnl_dump_args *args = arg;
48 FILE *fp = args->fp;
49 int ifindex = args->ifindex;
50 struct ifinfomsg *ifi = NLMSG_DATA(n);
51 int len = n->nlmsg_len;
52 struct rtattr *tb[IFLA_MAX + 1];
53 struct rtattr *ltb[IFLA_INET6_MAX + 1];
54 char abuf[256];
55
56 if (n->nlmsg_type != RTM_NEWLINK)
57 return -1;
58
59 len -= NLMSG_LENGTH(sizeof(*ifi));
60 if (len < 0)
61 return -1;
62
63 if (ifi->ifi_family != AF_INET6)
64 return -1;
65 if (ifi->ifi_index == 0)
66 return -1;
67 if (ifindex > 0 && ifi->ifi_index != ifindex)
68 return 0;
69 if (ifi->ifi_flags & (IFF_LOOPBACK | IFF_NOARP))
70 return 0;
71
72 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
73 if (!tb[IFLA_PROTINFO])
74 return -1;
75
76 parse_rtattr_nested(ltb, IFLA_INET6_MAX, tb[IFLA_PROTINFO]);
77 if (!ltb[IFLA_INET6_TOKEN]) {
78 fprintf(stderr, "Seems there's no support for IPv6 token!\n");
79 return -1;
80 }
81
82 fprintf(fp, "token %s ",
83 format_host(ifi->ifi_family,
84 RTA_PAYLOAD(ltb[IFLA_INET6_TOKEN]),
85 RTA_DATA(ltb[IFLA_INET6_TOKEN]),
86 abuf, sizeof(abuf)));
87 fprintf(fp, "dev %s ", ll_index_to_name(ifi->ifi_index));
88 fprintf(fp, "\n");
89 fflush(fp);
90
91 return 0;
92}
93
94static int iptoken_list(int argc, char **argv)
95{
96 int af = AF_INET6;
97 struct rtnl_dump_args da;
98 const struct rtnl_dump_filter_arg a[2] = {
99 { .filter = print_token, .arg1 = &da, },
100 { .filter = NULL, .arg1 = NULL, },
101 };
102
103 memset(&da, 0, sizeof(da));
104 da.fp = stdout;
105
106 while (argc > 0) {
107 if (strcmp(*argv, "dev") == 0) {
108 NEXT_ARG();
109 if ((da.ifindex = ll_name_to_index(*argv)) == 0)
110 invarg("dev is invalid\n", *argv);
111 break;
112 }
113 argc--; argv++;
114 }
115
116 if (rtnl_wilddump_request(&rth, af, RTM_GETLINK) < 0) {
117 perror("Cannot send dump request");
118 return -1;
119 }
120
121 if (rtnl_dump_filter_l(&rth, a) < 0) {
122 fprintf(stderr, "Dump terminated\n");
123 return -1;
124 }
125
126 return 0;
127}
128
129static int iptoken_set(int argc, char **argv)
130{
131 struct {
132 struct nlmsghdr n;
133 struct ifinfomsg ifi;
134 char buf[512];
135 } req;
136 struct rtattr *afs, *afs6;
137 bool have_token = false, have_dev = false;
138 inet_prefix addr;
139
140 memset(&addr, 0, sizeof(addr));
141 memset(&req, 0, sizeof(req));
142
143 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
144 req.n.nlmsg_flags = NLM_F_REQUEST;
145 req.n.nlmsg_type = RTM_SETLINK;
146 req.ifi.ifi_family = AF_INET6;
147
148 while (argc > 0) {
149 if (strcmp(*argv, "dev") == 0) {
150 NEXT_ARG();
151 if (!have_dev) {
152 if ((req.ifi.ifi_index =
153 ll_name_to_index(*argv)) == 0)
154 invarg("dev is invalid\n", *argv);
155 have_dev = true;
156 }
157 } else {
158 if (matches(*argv, "help") == 0)
159 usage();
160 if (!have_token) {
161 afs = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
162 afs6 = addattr_nest(&req.n, sizeof(req), AF_INET6);
163 get_prefix(&addr, *argv, req.ifi.ifi_family);
164 addattr_l(&req.n, sizeof(req), IFLA_INET6_TOKEN,
165 &addr.data, addr.bytelen);
166 addattr_nest_end(&req.n, afs6);
167 addattr_nest_end(&req.n, afs);
168 have_token = true;
169 }
170 }
171 argc--; argv++;
172 }
173
174 if (!have_token) {
175 fprintf(stderr, "Not enough information: token "
176 "is required.\n");
177 return -1;
178 }
179 if (!have_dev) {
180 fprintf(stderr, "Not enough information: \"dev\" "
181 "argument is required.\n");
182 return -1;
183 }
184
c079e121 185 if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
191b60bd
DB
186 return -2;
187
188 return 0;
189}
190
191int do_iptoken(int argc, char **argv)
192{
193 ll_init_map(&rth);
194
195 if (argc < 1) {
196 return iptoken_list(0, NULL);
197 } else if (matches(argv[0], "list") == 0 ||
473544d9 198 matches(argv[0], "lst") == 0 ||
191b60bd
DB
199 matches(argv[0], "show") == 0) {
200 return iptoken_list(argc - 1, argv + 1);
201 } else if (matches(argv[0], "set") == 0 ||
202 matches(argv[0], "add") == 0) {
203 return iptoken_set(argc - 1, argv + 1);
204 } else if (matches(argv[0], "get") == 0) {
205 return iptoken_list(argc - 1, argv + 1);
206 } else if (matches(argv[0], "help") == 0)
207 usage();
208
209 fprintf(stderr, "Command \"%s\" is unknown, try \"ip token help\".\n", *argv);
210 exit(-1);
211}