]>
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(struct nlmsghdr
*n
, void *arg
)
104 struct rtattr
*attrs
[SEG6_ATTR_MAX
+ 1];
105 struct genlmsghdr
*ghdr
;
106 int len
= n
->nlmsg_len
;
108 if (n
->nlmsg_type
!= genl_family
)
111 len
-= NLMSG_LENGTH(GENL_HDRLEN
);
115 ghdr
= NLMSG_DATA(n
);
117 parse_rtattr(attrs
, SEG6_ATTR_MAX
, (void *)ghdr
+ GENL_HDRLEN
, len
);
119 open_json_object(NULL
);
121 case SEG6_CMD_DUMPHMAC
:
122 print_dumphmac(attrs
);
125 case SEG6_CMD_GET_TUNSRC
:
134 static int seg6_do_cmd(void)
136 SEG6_REQUEST(req
, 1024, opts
.cmd
, NLM_F_REQUEST
);
137 struct nlmsghdr
*answer
;
138 int repl
= 0, dump
= 0;
140 if (genl_family
< 0) {
141 if (rtnl_open_byproto(&grth
, 0, NETLINK_GENERIC
) < 0) {
142 fprintf(stderr
, "Cannot open generic netlink socket\n");
145 genl_family
= genl_resolve_family(&grth
, SEG6_GENL_NAME
);
148 req
.n
.nlmsg_type
= genl_family
;
152 case SEG6_CMD_SETHMAC
:
154 addattr32(&req
.n
, sizeof(req
), SEG6_ATTR_HMACKEYID
, opts
.keyid
);
155 addattr8(&req
.n
, sizeof(req
), SEG6_ATTR_SECRETLEN
,
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
));
163 case SEG6_CMD_SET_TUNSRC
:
164 addattr_l(&req
.n
, sizeof(req
), SEG6_ATTR_DST
, opts
.addr
.data
,
165 sizeof(struct in6_addr
));
167 case SEG6_CMD_DUMPHMAC
:
170 case SEG6_CMD_GET_TUNSRC
:
175 if (!repl
&& !dump
) {
176 if (rtnl_talk(&grth
, &req
.n
, NULL
) < 0)
179 if (rtnl_talk(&grth
, &req
.n
, &answer
) < 0)
182 if (process_msg(answer
, stdout
) < 0) {
183 fprintf(stderr
, "Error parsing reply\n");
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");
197 if (rtnl_dump_filter(&grth
, process_msg
, stdout
) < 0) {
198 fprintf(stderr
, "Dump terminated\n");
208 int do_seg6(int argc
, char **argv
)
210 if (argc
< 1 || matches(*argv
, "help") == 0)
213 memset(&opts
, 0, sizeof(opts
));
215 if (matches(*argv
, "hmac") == 0) {
217 if (matches(*argv
, "show") == 0) {
218 opts
.cmd
= SEG6_CMD_DUMPHMAC
;
219 } else if (matches(*argv
, "set") == 0) {
221 if (get_u32(&opts
.keyid
, *argv
, 0) || opts
.keyid
== 0)
222 invarg("hmac KEYID value is invalid", *argv
);
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
;
229 invarg("hmac ALGO value is invalid", *argv
);
231 opts
.cmd
= SEG6_CMD_SETHMAC
;
232 opts
.pass
= getpass(HMAC_KEY_PROMPT
);
234 invarg("unknown", *argv
);
236 } else if (matches(*argv
, "tunsrc") == 0) {
238 if (matches(*argv
, "show") == 0) {
239 opts
.cmd
= SEG6_CMD_GET_TUNSRC
;
240 } else if (matches(*argv
, "set") == 0) {
242 opts
.cmd
= SEG6_CMD_SET_TUNSRC
;
243 get_addr(&opts
.addr
, *argv
, AF_INET6
);
245 invarg("unknown", *argv
);
248 invarg("unknown", *argv
);
251 return seg6_do_cmd();