diff options
Diffstat (limited to 'sbin/ipfw/context.c')
-rw-r--r-- | sbin/ipfw/context.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/sbin/ipfw/context.c b/sbin/ipfw/context.c new file mode 100644 index 0000000..bce576e --- /dev/null +++ b/sbin/ipfw/context.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013 Ermal Lu�i + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_var.h> + +#include <netinet/in.h> +#include <netinet/ip_fw.h> + +#include "ipfw2.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sysexits.h> +#include <string.h> +#include <errno.h> +#include <err.h> + +extern int ipfw_socket; + +int +ipfw_context_handler(int ac, char **av) +{ + ip_fw3_opheader *op3; + int error = 0; + uint32_t action = 0; + socklen_t len, nlen; + char *ifname; + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + if (!strncmp(*av, "list", strlen(*av))) { + action = IP_FW_CTX_GET; + av++; + ac--; + if (ac > 0) + errx(EX_DATAERR, "list: does not take any extra arguments."); + + } else { + co.ctx = atoi(*av); + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + if (!strncmp(*av, "create", strlen(*av))) + action = IP_FW_CTX_ADD; + else if (!strncmp(*av, "destroy", strlen(*av))) + action = IP_FW_CTX_DEL; + else { + if (!strncmp(*av, "madd", strlen(*av))) + action = IP_FW_CTX_ADDMEMBER; + else if (!strncmp(*av, "mdel", strlen(*av))) + action = IP_FW_CTX_DELMEMBER; + else + errx(EX_DATAERR, "Wrong parameters passed"); + + av++; + ac--; + NEED1("bad arguments, for usage summary ``ipfw''"); + + ifname = *av; + } + + ac--; + if (ac > 0) + errx(EX_DATAERR, "context handling: Too many arguments passed"); + + } + + if (co.test_only) + return (0); + + if (ipfw_socket < 0) + ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + if (ipfw_socket < 0) + err(EX_UNAVAILABLE, "socket"); + + switch (action) { + case IP_FW_CTX_ADD: + case IP_FW_CTX_DEL: + case IP_FW_CTX_SET: + len = sizeof(ip_fw3_opheader); + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, sizeof(ip_fw3_opheader)); + op3->opcode = action; + op3->ctxid = co.ctx; + error = setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len); + break; + case IP_FW_CTX_ADDMEMBER: + case IP_FW_CTX_DELMEMBER: + len = sizeof(ip_fw3_opheader) + strlen(ifname) + 1; + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, sizeof(ip_fw3_opheader) + strlen(ifname) + 1); + memcpy((op3 + 1), ifname, strlen(ifname)); + op3->opcode = action; + op3->ctxid = co.ctx; + error = setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, len); + break; + case IP_FW_CTX_GET: + len = sizeof(ip_fw3_opheader) + 1000; + nlen = len; + do { + if (nlen > len) { + len = nlen; + } + op3 = alloca(len); + /* Zero reserved fields */ + memset(op3, 0, len); + op3->opcode = action; + op3->ctxid = co.ctx; + nlen = len; + error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, &nlen); + } while (nlen > len && !error); + + if (!error) { + if (nlen == 0) + printf("There are no contexts defined\n"); + else + printf("Currently defined contexts and their members:\n%s\n", (char *)op3); + } else + err(EX_UNAVAILABLE, "Error returned: %s\n", strerror(error)); + + break; + } + + return (error); +} |