mirror_iproute2/ip/ipseg6.c
Matteo Croce 8589eb4efd treewide: refactor help messages
Every tool in the iproute2 package have one or more function to show
an help message to the user. Some of these functions print the help
line by line with a series of printf call, e.g. ip/xfrm_state.c does
60 fprintf calls.
If we group all the calls to a single one and just concatenate strings,
we save a lot of libc calls and thus object size. The size difference
of the compiled binaries calculated with bloat-o-meter is:

        ip/ip:
        add/remove: 0/0 grow/shrink: 5/15 up/down: 103/-4796 (-4693)
        Total: Before=672591, After=667898, chg -0.70%
        ip/rtmon:
        add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-54 (-54)
        Total: Before=48879, After=48825, chg -0.11%
        tc/tc:
        add/remove: 0/2 grow/shrink: 31/10 up/down: 882/-6133 (-5251)
        Total: Before=351912, After=346661, chg -1.49%
        bridge/bridge:
        add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-459 (-459)
        Total: Before=70502, After=70043, chg -0.65%
        misc/lnstat:
        add/remove: 0/1 grow/shrink: 1/0 up/down: 48/-486 (-438)
        Total: Before=9960, After=9522, chg -4.40%
        tipc/tipc:
        add/remove: 0/0 grow/shrink: 1/1 up/down: 18/-62 (-44)
        Total: Before=79182, After=79138, chg -0.06%

While at it, indent some strings which were starting at column 0,
and use tabs where possible, to have a consistent style across helps.

Signed-off-by: Matteo Croce <mcroce@redhat.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
2019-05-20 14:35:07 -07:00

254 lines
5.6 KiB
C

/*
* seg6.c "ip sr/seg6"
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation;
*
* Author: David Lebrun <david.lebrun@uclouvain.be>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/genetlink.h>
#include <linux/seg6_genl.h>
#include <linux/seg6_hmac.h>
#include "utils.h"
#include "ip_common.h"
#include "libgenl.h"
#include "json_print.h"
#define HMAC_KEY_PROMPT "Enter secret for HMAC key ID (blank to delete): "
static void usage(void)
{
fprintf(stderr,
"Usage: ip sr { COMMAND | help }\n"
" ip sr hmac show\n"
" ip sr hmac set KEYID ALGO\n"
" ip sr tunsrc show\n"
" ip sr tunsrc set ADDRESS\n"
"where ALGO := { sha1 | sha256 }\n");
exit(-1);
}
static struct rtnl_handle grth = { .fd = -1 };
static int genl_family = -1;
#define SEG6_REQUEST(_req, _bufsiz, _cmd, _flags) \
GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
SEG6_GENL_VERSION, _cmd, _flags)
static struct {
unsigned int cmd;
inet_prefix addr;
__u32 keyid;
const char *pass;
__u8 alg_id;
} opts;
static void print_dumphmac(struct rtattr *attrs[])
{
char secret[64];
char *algstr;
__u8 slen = rta_getattr_u8(attrs[SEG6_ATTR_SECRETLEN]);
__u8 alg_id = rta_getattr_u8(attrs[SEG6_ATTR_ALGID]);
memset(secret, 0, 64);
if (slen > 63) {
fprintf(stderr, "HMAC secret length %d > 63, truncated\n", slen);
slen = 63;
}
memcpy(secret, RTA_DATA(attrs[SEG6_ATTR_SECRET]), slen);
switch (alg_id) {
case SEG6_HMAC_ALGO_SHA1:
algstr = "sha1";
break;
case SEG6_HMAC_ALGO_SHA256:
algstr = "sha256";
break;
default:
algstr = "<unknown>";
}
print_uint(PRINT_ANY, "hmac", "hmac %u ",
rta_getattr_u32(attrs[SEG6_ATTR_HMACKEYID]));
print_string(PRINT_ANY, "algo", "algo %s ", algstr);
print_string(PRINT_ANY, "secret", "secret \"%s\"\n", secret);
}
static void print_tunsrc(struct rtattr *attrs[])
{
const char *dst
= rt_addr_n2a(AF_INET6, 16,
RTA_DATA(attrs[SEG6_ATTR_DST]));
print_string(PRINT_ANY, "tunsrc",
"tunsrc addr %s\n", dst);
}
static int process_msg(struct nlmsghdr *n, void *arg)
{
struct rtattr *attrs[SEG6_ATTR_MAX + 1];
struct genlmsghdr *ghdr;
int len = n->nlmsg_len;
if (n->nlmsg_type != genl_family)
return -1;
len -= NLMSG_LENGTH(GENL_HDRLEN);
if (len < 0)
return -1;
ghdr = NLMSG_DATA(n);
parse_rtattr(attrs, SEG6_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
open_json_object(NULL);
switch (ghdr->cmd) {
case SEG6_CMD_DUMPHMAC:
print_dumphmac(attrs);
break;
case SEG6_CMD_GET_TUNSRC:
print_tunsrc(attrs);
break;
}
close_json_object();
return 0;
}
static int seg6_do_cmd(void)
{
SEG6_REQUEST(req, 1024, opts.cmd, NLM_F_REQUEST);
struct nlmsghdr *answer;
int repl = 0, dump = 0;
if (genl_family < 0) {
if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) {
fprintf(stderr, "Cannot open generic netlink socket\n");
exit(1);
}
genl_family = genl_resolve_family(&grth, SEG6_GENL_NAME);
if (genl_family < 0)
exit(1);
req.n.nlmsg_type = genl_family;
}
switch (opts.cmd) {
case SEG6_CMD_SETHMAC:
{
addattr32(&req.n, sizeof(req), SEG6_ATTR_HMACKEYID, opts.keyid);
addattr8(&req.n, sizeof(req), SEG6_ATTR_SECRETLEN,
strlen(opts.pass));
addattr8(&req.n, sizeof(req), SEG6_ATTR_ALGID, opts.alg_id);
if (strlen(opts.pass))
addattr_l(&req.n, sizeof(req), SEG6_ATTR_SECRET,
opts.pass, strlen(opts.pass));
break;
}
case SEG6_CMD_SET_TUNSRC:
addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, opts.addr.data,
sizeof(struct in6_addr));
break;
case SEG6_CMD_DUMPHMAC:
dump = 1;
break;
case SEG6_CMD_GET_TUNSRC:
repl = 1;
break;
}
if (!repl && !dump) {
if (rtnl_talk(&grth, &req.n, NULL) < 0)
return -1;
} else if (repl) {
if (rtnl_talk(&grth, &req.n, &answer) < 0)
return -2;
new_json_obj(json);
if (process_msg(answer, stdout) < 0) {
fprintf(stderr, "Error parsing reply\n");
exit(1);
}
delete_json_obj();
free(answer);
} else {
req.n.nlmsg_flags |= NLM_F_DUMP;
req.n.nlmsg_seq = grth.dump = ++grth.seq;
if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
perror("Failed to send dump request");
exit(1);
}
new_json_obj(json);
if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) {
fprintf(stderr, "Dump terminated\n");
exit(1);
}
delete_json_obj();
fflush(stdout);
}
return 0;
}
int do_seg6(int argc, char **argv)
{
if (argc < 1 || matches(*argv, "help") == 0)
usage();
memset(&opts, 0, sizeof(opts));
if (matches(*argv, "hmac") == 0) {
NEXT_ARG();
if (matches(*argv, "show") == 0) {
opts.cmd = SEG6_CMD_DUMPHMAC;
} else if (matches(*argv, "set") == 0) {
NEXT_ARG();
if (get_u32(&opts.keyid, *argv, 0) || opts.keyid == 0)
invarg("hmac KEYID value is invalid", *argv);
NEXT_ARG();
if (strcmp(*argv, "sha1") == 0) {
opts.alg_id = SEG6_HMAC_ALGO_SHA1;
} else if (strcmp(*argv, "sha256") == 0) {
opts.alg_id = SEG6_HMAC_ALGO_SHA256;
} else {
invarg("hmac ALGO value is invalid", *argv);
}
opts.cmd = SEG6_CMD_SETHMAC;
opts.pass = getpass(HMAC_KEY_PROMPT);
} else {
invarg("unknown", *argv);
}
} else if (matches(*argv, "tunsrc") == 0) {
NEXT_ARG();
if (matches(*argv, "show") == 0) {
opts.cmd = SEG6_CMD_GET_TUNSRC;
} else if (matches(*argv, "set") == 0) {
NEXT_ARG();
opts.cmd = SEG6_CMD_SET_TUNSRC;
get_addr(&opts.addr, *argv, AF_INET6);
} else {
invarg("unknown", *argv);
}
} else {
invarg("unknown", *argv);
}
return seg6_do_cmd();
}