]>
git.proxmox.com Git - mirror_iproute2.git/blob - ip/ipseg6.c
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;
8 * Author: David Lebrun <david.lebrun@uclouvain.be>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <arpa/inet.h>
19 #include <sys/ioctl.h>
22 #include <linux/genetlink.h>
23 #include <linux/seg6_genl.h>
24 #include <linux/seg6_hmac.h>
27 #include "ip_common.h"
29 #include "json_print.h"
31 #define HMAC_KEY_PROMPT "Enter secret for HMAC key ID (blank to delete): "
33 static void usage(void)
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");
44 static struct rtnl_handle grth
= { .fd
= -1 };
45 static int genl_family
= -1;
47 #define SEG6_REQUEST(_req, _bufsiz, _cmd, _flags) \
48 GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
49 SEG6_GENL_VERSION, _cmd, _flags)
59 static void print_dumphmac(struct rtattr
*attrs
[])
63 __u8 slen
= rta_getattr_u8(attrs
[SEG6_ATTR_SECRETLEN
]);
64 __u8 alg_id
= rta_getattr_u8(attrs
[SEG6_ATTR_ALGID
]);
66 memset(secret
, 0, 64);
69 fprintf(stderr
, "HMAC secret length %d > 63, truncated\n", slen
);
73 memcpy(secret
, RTA_DATA(attrs
[SEG6_ATTR_SECRET
]), slen
);
76 case SEG6_HMAC_ALGO_SHA1
:
79 case SEG6_HMAC_ALGO_SHA256
:
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
);
92 static void print_tunsrc(struct rtattr
*attrs
[])
95 = rt_addr_n2a(AF_INET6
, 16,
96 RTA_DATA(attrs
[SEG6_ATTR_DST
]));
98 print_string(PRINT_ANY
, "tunsrc",
99 "tunsrc addr %s\n", dst
);
102 static int process_msg(const struct sockaddr_nl
*who
, struct nlmsghdr
*n
,
105 struct rtattr
*attrs
[SEG6_ATTR_MAX
+ 1];
106 struct genlmsghdr
*ghdr
;
107 int len
= n
->nlmsg_len
;
109 if (n
->nlmsg_type
!= genl_family
)
112 len
-= NLMSG_LENGTH(GENL_HDRLEN
);
116 ghdr
= NLMSG_DATA(n
);
118 parse_rtattr(attrs
, SEG6_ATTR_MAX
, (void *)ghdr
+ GENL_HDRLEN
, len
);
120 open_json_object(NULL
);
122 case SEG6_CMD_DUMPHMAC
:
123 print_dumphmac(attrs
);
126 case SEG6_CMD_GET_TUNSRC
:
135 static int seg6_do_cmd(void)
137 SEG6_REQUEST(req
, 1024, opts
.cmd
, NLM_F_REQUEST
);
138 struct nlmsghdr
*answer
;
139 int repl
= 0, dump
= 0;
141 if (genl_family
< 0) {
142 if (rtnl_open_byproto(&grth
, 0, NETLINK_GENERIC
) < 0) {
143 fprintf(stderr
, "Cannot open generic netlink socket\n");
146 genl_family
= genl_resolve_family(&grth
, SEG6_GENL_NAME
);
149 req
.n
.nlmsg_type
= genl_family
;
153 case SEG6_CMD_SETHMAC
:
155 addattr32(&req
.n
, sizeof(req
), SEG6_ATTR_HMACKEYID
, opts
.keyid
);
156 addattr8(&req
.n
, sizeof(req
), SEG6_ATTR_SECRETLEN
,
158 addattr8(&req
.n
, sizeof(req
), SEG6_ATTR_ALGID
, opts
.alg_id
);
159 if (strlen(opts
.pass
))
160 addattr_l(&req
.n
, sizeof(req
), SEG6_ATTR_SECRET
,
161 opts
.pass
, strlen(opts
.pass
));
164 case SEG6_CMD_SET_TUNSRC
:
165 addattr_l(&req
.n
, sizeof(req
), SEG6_ATTR_DST
, opts
.addr
.data
,
166 sizeof(struct in6_addr
));
168 case SEG6_CMD_DUMPHMAC
:
171 case SEG6_CMD_GET_TUNSRC
:
176 if (!repl
&& !dump
) {
177 if (rtnl_talk(&grth
, &req
.n
, NULL
) < 0)
180 if (rtnl_talk(&grth
, &req
.n
, &answer
) < 0)
183 if (process_msg(NULL
, answer
, stdout
) < 0) {
184 fprintf(stderr
, "Error parsing reply\n");
190 req
.n
.nlmsg_flags
|= NLM_F_DUMP
;
191 req
.n
.nlmsg_seq
= grth
.dump
= ++grth
.seq
;
192 if (rtnl_send(&grth
, &req
, req
.n
.nlmsg_len
) < 0) {
193 perror("Failed to send dump request");
198 if (rtnl_dump_filter(&grth
, process_msg
, stdout
) < 0) {
199 fprintf(stderr
, "Dump terminated\n");
209 int do_seg6(int argc
, char **argv
)
211 if (argc
< 1 || matches(*argv
, "help") == 0)
214 memset(&opts
, 0, sizeof(opts
));
216 if (matches(*argv
, "hmac") == 0) {
218 if (matches(*argv
, "show") == 0) {
219 opts
.cmd
= SEG6_CMD_DUMPHMAC
;
220 } else if (matches(*argv
, "set") == 0) {
222 if (get_u32(&opts
.keyid
, *argv
, 0) || opts
.keyid
== 0)
223 invarg("hmac KEYID value is invalid", *argv
);
225 if (strcmp(*argv
, "sha1") == 0) {
226 opts
.alg_id
= SEG6_HMAC_ALGO_SHA1
;
227 } else if (strcmp(*argv
, "sha256") == 0) {
228 opts
.alg_id
= SEG6_HMAC_ALGO_SHA256
;
230 invarg("hmac ALGO value is invalid", *argv
);
232 opts
.cmd
= SEG6_CMD_SETHMAC
;
233 opts
.pass
= getpass(HMAC_KEY_PROMPT
);
235 invarg("unknown", *argv
);
237 } else if (matches(*argv
, "tunsrc") == 0) {
239 if (matches(*argv
, "show") == 0) {
240 opts
.cmd
= SEG6_CMD_GET_TUNSRC
;
241 } else if (matches(*argv
, "set") == 0) {
243 opts
.cmd
= SEG6_CMD_SET_TUNSRC
;
244 get_addr(&opts
.addr
, *argv
, AF_INET6
);
246 invarg("unknown", *argv
);
249 invarg("unknown", *argv
);
252 return seg6_do_cmd();