]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/ipseg6.c
ipnetns: parse nsid as a signed integer
[mirror_iproute2.git] / ip / ipseg6.c
CommitLineData
93863328
DL
1/*
2 * seg6.c "ip sr/seg6"
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 * version 2 as published by the Free Software Foundation;
7 *
8 * Author: David Lebrun <david.lebrun@uclouvain.be>
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <unistd.h>
15#include <errno.h>
16#include <sys/types.h>
17#include <sys/socket.h>
18#include <arpa/inet.h>
19#include <sys/ioctl.h>
20#include <linux/if.h>
21
22#include <linux/genetlink.h>
23#include <linux/seg6_genl.h>
24#include <linux/seg6_hmac.h>
25
26#include "utils.h"
27#include "ip_common.h"
28#include "libgenl.h"
111f79ad 29#include "json_print.h"
93863328
DL
30
31#define HMAC_KEY_PROMPT "Enter secret for HMAC key ID (blank to delete): "
32
33static void usage(void)
34{
35 fprintf(stderr, "Usage: ip sr { COMMAND | help }\n");
36 fprintf(stderr, " ip sr hmac show\n");
37 fprintf(stderr, " ip sr hmac set KEYID ALGO\n");
38 fprintf(stderr, " ip sr tunsrc show\n");
39 fprintf(stderr, " ip sr tunsrc set ADDRESS\n");
40 fprintf(stderr, "where ALGO := { sha1 | sha256 }\n");
41 exit(-1);
42}
43
44static struct rtnl_handle grth = { .fd = -1 };
45static int genl_family = -1;
46
47#define SEG6_REQUEST(_req, _bufsiz, _cmd, _flags) \
48 GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
49 SEG6_GENL_VERSION, _cmd, _flags)
50
51static struct {
52 unsigned int cmd;
6caad8f5 53 inet_prefix addr;
93863328
DL
54 __u32 keyid;
55 const char *pass;
56 __u8 alg_id;
57} opts;
58
111f79ad
SH
59static void print_dumphmac(struct rtattr *attrs[])
60{
61 char secret[64];
62 char *algstr;
63 __u8 slen = rta_getattr_u8(attrs[SEG6_ATTR_SECRETLEN]);
64 __u8 alg_id = rta_getattr_u8(attrs[SEG6_ATTR_ALGID]);
65
66 memset(secret, 0, 64);
67
68 if (slen > 63) {
69 fprintf(stderr, "HMAC secret length %d > 63, truncated\n", slen);
70 slen = 63;
71 }
72
73 memcpy(secret, RTA_DATA(attrs[SEG6_ATTR_SECRET]), slen);
74
75 switch (alg_id) {
76 case SEG6_HMAC_ALGO_SHA1:
77 algstr = "sha1";
78 break;
79 case SEG6_HMAC_ALGO_SHA256:
80 algstr = "sha256";
81 break;
82 default:
83 algstr = "<unknown>";
84 }
85
86 print_uint(PRINT_ANY, "hmac", "hmac %u ",
87 rta_getattr_u32(attrs[SEG6_ATTR_HMACKEYID]));
88 print_string(PRINT_ANY, "algo", "algo %s ", algstr);
89 print_string(PRINT_ANY, "secret", "secret \"%s\"\n", secret);
90}
91
92static void print_tunsrc(struct rtattr *attrs[])
93{
94 const char *dst
95 = rt_addr_n2a(AF_INET6, 16,
96 RTA_DATA(attrs[SEG6_ATTR_DST]));
97
98 print_string(PRINT_ANY, "tunsrc",
99 "tunsrc addr %s\n", dst);
100}
101
cd554f2c 102static int process_msg(struct nlmsghdr *n, void *arg)
93863328
DL
103{
104 struct rtattr *attrs[SEG6_ATTR_MAX + 1];
105 struct genlmsghdr *ghdr;
93863328
DL
106 int len = n->nlmsg_len;
107
108 if (n->nlmsg_type != genl_family)
109 return -1;
110
111 len -= NLMSG_LENGTH(GENL_HDRLEN);
112 if (len < 0)
113 return -1;
114
115 ghdr = NLMSG_DATA(n);
116
117 parse_rtattr(attrs, SEG6_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
118
111f79ad 119 open_json_object(NULL);
93863328
DL
120 switch (ghdr->cmd) {
121 case SEG6_CMD_DUMPHMAC:
111f79ad 122 print_dumphmac(attrs);
93863328 123 break;
111f79ad 124
93863328 125 case SEG6_CMD_GET_TUNSRC:
111f79ad 126 print_tunsrc(attrs);
93863328
DL
127 break;
128 }
111f79ad 129 close_json_object();
93863328
DL
130
131 return 0;
132}
133
134static int seg6_do_cmd(void)
135{
136 SEG6_REQUEST(req, 1024, opts.cmd, NLM_F_REQUEST);
86bf43c7 137 struct nlmsghdr *answer;
93863328
DL
138 int repl = 0, dump = 0;
139
140 if (genl_family < 0) {
141 if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) {
142 fprintf(stderr, "Cannot open generic netlink socket\n");
143 exit(1);
144 }
145 genl_family = genl_resolve_family(&grth, SEG6_GENL_NAME);
146 if (genl_family < 0)
147 exit(1);
148 req.n.nlmsg_type = genl_family;
149 }
150
151 switch (opts.cmd) {
152 case SEG6_CMD_SETHMAC:
153 {
154 addattr32(&req.n, sizeof(req), SEG6_ATTR_HMACKEYID, opts.keyid);
155 addattr8(&req.n, sizeof(req), SEG6_ATTR_SECRETLEN,
156 strlen(opts.pass));
157 addattr8(&req.n, sizeof(req), SEG6_ATTR_ALGID, opts.alg_id);
158 if (strlen(opts.pass))
159 addattr_l(&req.n, sizeof(req), SEG6_ATTR_SECRET,
160 opts.pass, strlen(opts.pass));
161 break;
162 }
163 case SEG6_CMD_SET_TUNSRC:
6caad8f5 164 addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, opts.addr.data,
93863328
DL
165 sizeof(struct in6_addr));
166 break;
167 case SEG6_CMD_DUMPHMAC:
168 dump = 1;
169 break;
170 case SEG6_CMD_GET_TUNSRC:
171 repl = 1;
172 break;
173 }
174
175 if (!repl && !dump) {
86bf43c7 176 if (rtnl_talk(&grth, &req.n, NULL) < 0)
93863328
DL
177 return -1;
178 } else if (repl) {
86bf43c7 179 if (rtnl_talk(&grth, &req.n, &answer) < 0)
93863328 180 return -2;
111f79ad 181 new_json_obj(json);
cd554f2c 182 if (process_msg(answer, stdout) < 0) {
93863328
DL
183 fprintf(stderr, "Error parsing reply\n");
184 exit(1);
185 }
111f79ad 186 delete_json_obj();
86bf43c7 187 free(answer);
93863328
DL
188 } else {
189 req.n.nlmsg_flags |= NLM_F_DUMP;
190 req.n.nlmsg_seq = grth.dump = ++grth.seq;
191 if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
192 perror("Failed to send dump request");
193 exit(1);
194 }
195
111f79ad 196 new_json_obj(json);
93863328
DL
197 if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) {
198 fprintf(stderr, "Dump terminated\n");
199 exit(1);
200 }
111f79ad
SH
201 delete_json_obj();
202 fflush(stdout);
93863328
DL
203 }
204
205 return 0;
206}
207
208int do_seg6(int argc, char **argv)
209{
210 if (argc < 1 || matches(*argv, "help") == 0)
211 usage();
212
213 memset(&opts, 0, sizeof(opts));
214
215 if (matches(*argv, "hmac") == 0) {
216 NEXT_ARG();
217 if (matches(*argv, "show") == 0) {
218 opts.cmd = SEG6_CMD_DUMPHMAC;
219 } else if (matches(*argv, "set") == 0) {
220 NEXT_ARG();
221 if (get_u32(&opts.keyid, *argv, 0) || opts.keyid == 0)
222 invarg("hmac KEYID value is invalid", *argv);
223 NEXT_ARG();
224 if (strcmp(*argv, "sha1") == 0) {
225 opts.alg_id = SEG6_HMAC_ALGO_SHA1;
226 } else if (strcmp(*argv, "sha256") == 0) {
227 opts.alg_id = SEG6_HMAC_ALGO_SHA256;
228 } else {
229 invarg("hmac ALGO value is invalid", *argv);
230 }
231 opts.cmd = SEG6_CMD_SETHMAC;
232 opts.pass = getpass(HMAC_KEY_PROMPT);
233 } else {
234 invarg("unknown", *argv);
235 }
236 } else if (matches(*argv, "tunsrc") == 0) {
237 NEXT_ARG();
238 if (matches(*argv, "show") == 0) {
239 opts.cmd = SEG6_CMD_GET_TUNSRC;
240 } else if (matches(*argv, "set") == 0) {
241 NEXT_ARG();
242 opts.cmd = SEG6_CMD_SET_TUNSRC;
6caad8f5 243 get_addr(&opts.addr, *argv, AF_INET6);
93863328
DL
244 } else {
245 invarg("unknown", *argv);
246 }
247 } else {
248 invarg("unknown", *argv);
249 }
250
251 return seg6_do_cmd();
252}