ip6addrctl(8): Teach ip6addrctl to attach and run itself in a jail

This will make it easier to manage address selection policies of vnet
jails, especially for those light weighted OCI containers or slim jails.

Requested by:	dfr
Reviewed by:	dfr, markj
MFC after:	1 week
Relnotes:	yes
Differential Revision:	https://reviews.freebsd.org/D48679
This commit is contained in:
Zhenlei Huang 2025-01-29 18:00:07 +08:00
parent 13ce55b66f
commit 6dcdd79a25
3 changed files with 86 additions and 18 deletions

View file

@ -1,5 +1,12 @@
.include <src.opts.mk>
PACKAGE= runtime
PROG= ip6addrctl
MAN= ip6addrctl.8
.if ${MK_JAIL} != "no"
CFLAGS+= -DJAIL
LIBADD+= jail
.endif
.include <bsd.prog.mk>

View file

@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd August 10, 2024
.Dd January 29, 2025
.Dt IP6ADDRCTL 8
.Os
.\"
@ -37,16 +37,21 @@
.\"
.Sh SYNOPSIS
.Nm
.Op Fl j Ar jail
.Op Cm show
.Nm
.Op Fl j Ar jail
.Cm add
.Ar prefix precedence label
.Nm
.Op Fl j Ar jail
.Cm delete
.Ar prefix
.Nm
.Op Fl j Ar jail
.Cm flush
.Nm
.Op Fl j Ar jail
.Cm install
.Ar configfile
.\"
@ -62,6 +67,10 @@ is invoked without an argument or with a single argument
it prints the content of the policy table currently installed in the
kernel.
.Pp
To operate inside a jail, the option
.Op Fl j Ar jail
should precede other options.
.Pp
To modify the table, the following operations are available:
.Bl -tag -width indent
.It Cm add Ar prefix precedence label
@ -100,6 +109,7 @@ In the configuration file, lines beginning with the pound-sign
.Pq Ql #
are
comments and are ignored.
Note that the configuration file will be processed before attaching to a jail.
.El
.\"
.Sh EXIT STATUS

View file

@ -36,6 +36,9 @@
#include <sys/queue.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#ifdef JAIL
#include <sys/jail.h>
#endif
#include <sys/sysctl.h>
#include <net/if.h>
@ -45,12 +48,18 @@
#include <stdlib.h>
#include <netdb.h>
#ifdef JAIL
#include <jail.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <err.h>
#ifdef JAIL
static char *jailname;
#endif
static char *configfile;
struct policyqueue {
@ -61,6 +70,7 @@ TAILQ_HEAD(policyhead, policyqueue);
static struct policyhead policyhead = TAILQ_HEAD_INITIALIZER(policyhead);
static void usage(void) __dead2;
static void attach_jail(void);
static void get_policy(void);
static void dump_policy(void);
static int mask2plen(struct sockaddr_in6 *);
@ -75,27 +85,51 @@ static void flush_policy(void);
int
main(int argc, char *argv[])
{
if (argc == 1 || (argc == 2 && strcasecmp(argv[1], "show") == 0)) {
int ch;
while ((ch = getopt(argc, argv, "j:")) != -1) {
switch (ch) {
case 'j':
#ifdef JAIL
if ((jailname = optarg) == NULL)
usage();
#else
errx(1, "not built with jail support");
#endif
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc == 0 || (argc == 1 && strcasecmp(argv[0], "show") == 0)) {
attach_jail();
get_policy();
dump_policy();
} else if (strcasecmp(argv[1], "add") == 0) {
if (argc != 5)
} else if (strcasecmp(argv[0], "add") == 0) {
if (argc != 4)
usage();
add_policy(argv[2], argv[3], argv[4]);
} else if (strcasecmp(argv[1], "delete") == 0) {
if (argc != 3)
usage();
delete_policy(argv[2]);
} else if (strcasecmp(argv[1], "flush") == 0) {
attach_jail();
add_policy(argv[1], argv[2], argv[3]);
} else if (strcasecmp(argv[0], "delete") == 0) {
if (argc != 2)
usage();
attach_jail();
delete_policy(argv[1]);
} else if (strcasecmp(argv[0], "flush") == 0) {
if (argc != 1)
usage();
attach_jail();
get_policy();
flush_policy();
} else if (strcasecmp(argv[1], "install") == 0) {
if (argc != 3)
} else if (strcasecmp(argv[0], "install") == 0) {
if (argc != 2)
usage();
configfile = argv[2];
configfile = argv[1];
make_policy_fromfile(configfile);
attach_jail();
set_policy();
} else
usage();
@ -103,6 +137,23 @@ main(int argc, char *argv[])
exit(0);
}
static void
attach_jail(void)
{
#ifdef JAIL
int jid;
if (jailname == NULL)
return;
jid = jail_getid(jailname);
if (jid == -1)
errx(1, "jail not found");
if (jail_attach(jid) != 0)
errx(1, "cannot attach to jail");
#endif
}
static void
get_policy(void)
{
@ -445,12 +496,12 @@ flush_policy(void)
static void
usage(void)
{
fprintf(stderr, "usage: ip6addrctl [show]\n");
fprintf(stderr, " ip6addrctl add "
fprintf(stderr, "usage: ip6addrctl [-j jail] [show]\n");
fprintf(stderr, " ip6addrctl [-j jail] add "
"<prefix> <precedence> <label>\n");
fprintf(stderr, " ip6addrctl delete <prefix>\n");
fprintf(stderr, " ip6addrctl flush\n");
fprintf(stderr, " ip6addrctl install <configfile>\n");
fprintf(stderr, " ip6addrctl [-j jail] delete <prefix>\n");
fprintf(stderr, " ip6addrctl [-j jail] flush\n");
fprintf(stderr, " ip6addrctl [-j jail] install <configfile>\n");
exit(1);
}