144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * src/nl-addr-add.c     Add addresses
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
55e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf *	modify it under the terms of the GNU General Public License as
65e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf *	published by the Free Software Foundation version 2 of the License.
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
88808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf
118808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#include <netlink/cli/utils.h>
128808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#include <netlink/cli/addr.h>
138808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#include <netlink/cli/link.h>
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf
155e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Grafstatic int quiet = 0;
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf
175e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Grafstatic void print_usage(void)
185e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf{
195e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	printf(
20ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"Usage: nl-addr-add [OPTION]... [ADDRESS]\n"
21ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"\n"
22ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"Options\n"
23ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"     --replace             Replace the address if it exists.\n"
24ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf" -q, --quiet               Do not print informal notifications.\n"
25ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf" -h, --help                Show this help.\n"
26ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf" -v, --version             Show versioning information.\n"
27ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"\n"
28ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"Address Options\n"
29ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf" -a, --local=ADDR          Address to be considered local.\n"
30ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf" -d, --dev=DEV             Device the address should be assigned to.\n"
31ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"     --family=FAMILY       Address family (normally autodetected).\n"
32ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"     --broadcast=ADDR      Broadcast address of network (IPv4).\n"
33ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"     --peer=ADDR           Peer address (IPv4).\n"
34ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"     --label=STRING        Additional address label (IPv4).\n"
35ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"     --scope=SCOPE         Scope of local address (IPv4).\n"
36ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"     --preferred=TIME      Preferred lifetime (IPv6).\n"
37ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf"     --valid=TIME          Valid lifetime (IPv6).\n"
385e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	);
3944d362409d5469aed47d19e7908d19bd194493aThomas Graf
405e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	exit(0);
415e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf}
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf
435e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Grafint main(int argc, char *argv[])
445e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf{
455e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	struct nl_sock *sock;
465e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	struct rtnl_addr *addr;
475e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	struct nl_cache *link_cache;
485e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	struct nl_dump_params dp = {
49d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf		.dp_type = NL_DUMP_LINE,
505e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		.dp_fd = stdout,
515e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	};
52ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf	int err, nlflags = NLM_F_CREATE;
535e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf
548808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf	sock = nl_cli_alloc_socket();
558808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf	nl_cli_connect(sock, NETLINK_ROUTE);
568808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf	link_cache = nl_cli_link_alloc_cache(sock);
578808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf 	addr = nl_cli_addr_alloc();
585e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf
595e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	for (;;) {
605e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		int c, optidx = 0;
615e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		enum {
625e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			ARG_FAMILY = 257,
635e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			ARG_LABEL = 258,
645e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			ARG_PEER,
655e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			ARG_SCOPE,
665e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			ARG_BROADCAST,
67ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf			ARG_REPLACE,
68ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf			ARG_PREFERRED,
69ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf			ARG_VALID,
705e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		};
715e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		static struct option long_opts[] = {
72ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf			{ "replace", 0, 0, ARG_REPLACE },
735e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "quiet", 0, 0, 'q' },
745e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "help", 0, 0, 'h' },
755e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "version", 0, 0, 'v' },
765e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "local", 1, 0, 'a' },
775e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "dev", 1, 0, 'd' },
785e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "family", 1, 0, ARG_FAMILY },
795e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "label", 1, 0, ARG_LABEL },
805e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "peer", 1, 0, ARG_PEER },
815e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "scope", 1, 0, ARG_SCOPE },
825e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ "broadcast", 1, 0, ARG_BROADCAST },
83ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf			{ "preferred", 1, 0, ARG_PREFERRED },
84ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf			{ "valid", 1, 0, ARG_VALID },
855e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			{ 0, 0, 0, 0 }
865e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		};
875e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf
885e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		c = getopt_long(argc, argv, "qhva:d:", long_opts, &optidx);
895e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		if (c == -1)
905e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf			break;
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf
925e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		switch (c) {
93ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf		case '?': exit(NLE_INVAL);
94ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf		case ARG_REPLACE: nlflags |= NLM_F_REPLACE; break;
955e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		case 'q': quiet = 1; break;
965e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		case 'h': print_usage(); break;
978808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case 'v': nl_cli_print_version(); break;
988808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case 'a': nl_cli_addr_parse_local(addr, optarg); break;
998808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case 'd': nl_cli_addr_parse_dev(addr, link_cache, optarg); break;
1008808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case ARG_FAMILY: nl_cli_addr_parse_family(addr, optarg); break;
1018808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case ARG_LABEL: nl_cli_addr_parse_label(addr, optarg); break;
1028808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case ARG_PEER: nl_cli_addr_parse_peer(addr, optarg); break;
1038808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case ARG_SCOPE: nl_cli_addr_parse_scope(addr, optarg); break;
1048808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case ARG_BROADCAST: nl_cli_addr_parse_broadcast(addr, optarg); break;
1058808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case ARG_PREFERRED: nl_cli_addr_parse_preferred(addr, optarg); break;
1068808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		case ARG_VALID: nl_cli_addr_parse_valid(addr, optarg); break;
1075e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		}
1085e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf 	}
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf
110ab578b9ca00b19ad6b66283ec08d004f9fc391d6Thomas Graf	if ((err = rtnl_addr_add(sock, addr, nlflags)) < 0)
1118808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf		nl_cli_fatal(err, "Unable to add address: %s",
1128808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf			     nl_geterror(err));
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf
1145e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	if (!quiet) {
1155e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		printf("Added ");
1165e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf		nl_object_dump(OBJ_CAST(addr), &dp);
1175e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf 	}
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf
1195e732ad075e54ceb9f9e94fadbcec2e83d971b52Thomas Graf	return 0;
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf}
121