Merge branch 'master' into net-2.6.25
This commit is contained in:
commit
e50e9f9123
|
|
@ -298,9 +298,9 @@ Do not use it, if you do not understand what this operation really does.
|
||||||
|
|
||||||
\vskip 1mm
|
\vskip 1mm
|
||||||
\begin{NB}
|
\begin{NB}
|
||||||
The {\tt ip} utility does not change the \verb|PROMISC|
|
The \verb|PROMISC| and \verb|ALLMULTI| flags are considered
|
||||||
or \verb|ALLMULTI| flags. These flags are considered
|
obsolete and should not be changed administratively, though
|
||||||
obsolete and should not be changed administratively.
|
the {\tt ip} utility will allow that.
|
||||||
\end{NB}
|
\end{NB}
|
||||||
|
|
||||||
\paragraph{Warning:} If multiple parameter changes are requested,
|
\paragraph{Warning:} If multiple parameter changes are requested,
|
||||||
|
|
@ -450,13 +450,6 @@ or not implemented (\verb|DEBUG|) or specific to some devices
|
||||||
(\verb|MASTER|, \verb|AUTOMEDIA| and \verb|PORTSEL|). We do not discuss
|
(\verb|MASTER|, \verb|AUTOMEDIA| and \verb|PORTSEL|). We do not discuss
|
||||||
them here.
|
them here.
|
||||||
\end{NB}
|
\end{NB}
|
||||||
\begin{NB}
|
|
||||||
The values of \verb|PROMISC| and \verb|ALLMULTI| flags
|
|
||||||
shown by the \verb|ifconfig| utility and by the \verb|ip| utility
|
|
||||||
are {\em different\/}. \verb|ip link ls| shows the true device state,
|
|
||||||
while \verb|ifconfig| shows the virtual state which was set with
|
|
||||||
\verb|ifconfig| itself.
|
|
||||||
\end{NB}
|
|
||||||
|
|
||||||
|
|
||||||
The second line contains information on the link layer addresses
|
The second line contains information on the link layer addresses
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef __LINUX_TC_NAT_H
|
||||||
|
#define __LINUX_TC_NAT_H
|
||||||
|
|
||||||
|
#include <linux/pkt_cls.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define TCA_ACT_NAT 9
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TCA_NAT_UNSPEC,
|
||||||
|
TCA_NAT_PARMS,
|
||||||
|
TCA_NAT_TM,
|
||||||
|
__TCA_NAT_MAX
|
||||||
|
};
|
||||||
|
#define TCA_NAT_MAX (__TCA_NAT_MAX - 1)
|
||||||
|
|
||||||
|
#define TCA_NAT_FLAG_EGRESS 1
|
||||||
|
|
||||||
|
struct tc_nat
|
||||||
|
{
|
||||||
|
tc_gen;
|
||||||
|
__be32 old_addr;
|
||||||
|
__be32 new_addr;
|
||||||
|
__be32 mask;
|
||||||
|
__u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -632,6 +632,6 @@ int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rt
|
||||||
rta = RTA_DATA(rta) + RTA_ALIGN(len);
|
rta = RTA_DATA(rta) + RTA_ALIGN(len);
|
||||||
return parse_rtattr_nested(tb, max, rta);
|
return parse_rtattr_nested(tb, max, rta);
|
||||||
}
|
}
|
||||||
memset(tb, 0, sizeof(struct rtattr *) * max);
|
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
lib/utils.c
45
lib/utils.c
|
|
@ -47,6 +47,48 @@ int get_integer(int *val, const char *arg, int base)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* a valid netmask must be 2^n - 1 */
|
||||||
|
static int is_valid_netmask(const inet_prefix *addr)
|
||||||
|
{
|
||||||
|
uint32_t host;
|
||||||
|
|
||||||
|
if (addr->family != AF_INET)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
host = ~ntohl(addr->data[0]);
|
||||||
|
|
||||||
|
return (host & (host + 1)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned cidr(const inet_prefix *addr)
|
||||||
|
{
|
||||||
|
unsigned bits = 0;
|
||||||
|
u_int32_t mask;
|
||||||
|
|
||||||
|
for (mask = ntohl(addr->data[0]); mask; mask <<= 1)
|
||||||
|
++bits;
|
||||||
|
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_netmask(unsigned *val, const char *arg, int base)
|
||||||
|
{
|
||||||
|
inet_prefix addr;
|
||||||
|
|
||||||
|
if (!get_unsigned(val, arg, base))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* try coverting dotted quad to CIDR */
|
||||||
|
if (!get_addr_1(&addr, arg, AF_INET)) {
|
||||||
|
if (is_valid_netmask(&addr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*val = cidr(&addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int get_unsigned(unsigned *val, const char *arg, int base)
|
int get_unsigned(unsigned *val, const char *arg, int base)
|
||||||
{
|
{
|
||||||
unsigned long res;
|
unsigned long res;
|
||||||
|
|
@ -304,7 +346,8 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)
|
||||||
dst->bitlen = 32;
|
dst->bitlen = 32;
|
||||||
}
|
}
|
||||||
if (slash) {
|
if (slash) {
|
||||||
if (get_unsigned(&plen, slash+1, 0) || plen > dst->bitlen) {
|
if (get_netmask(&plen, slash+1, 0)
|
||||||
|
|| plen > dst->bitlen) {
|
||||||
err = -1;
|
err = -1;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ TCMODULES += q_htb.o
|
||||||
TCMODULES += m_gact.o
|
TCMODULES += m_gact.o
|
||||||
TCMODULES += m_mirred.o
|
TCMODULES += m_mirred.o
|
||||||
TCMODULES += m_ipt.o
|
TCMODULES += m_ipt.o
|
||||||
|
TCMODULES += m_nat.o
|
||||||
TCMODULES += m_pedit.o
|
TCMODULES += m_pedit.o
|
||||||
TCMODULES += p_ip.o
|
TCMODULES += p_ip.o
|
||||||
TCMODULES += p_icmp.o
|
TCMODULES += p_icmp.o
|
||||||
|
|
|
||||||
29
tc/f_fw.c
29
tc/f_fw.c
|
|
@ -40,19 +40,30 @@ static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **a
|
||||||
|
|
||||||
memset(&tp, 0, sizeof(tp));
|
memset(&tp, 0, sizeof(tp));
|
||||||
|
|
||||||
|
tail = NLMSG_TAIL(n);
|
||||||
|
addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);
|
||||||
|
|
||||||
if (handle) {
|
if (handle) {
|
||||||
|
char *slash;
|
||||||
|
__u32 mask = 0;
|
||||||
|
if ((slash = strchr(handle, '/')) != NULL)
|
||||||
|
*slash = '\0';
|
||||||
if (get_u32(&t->tcm_handle, handle, 0)) {
|
if (get_u32(&t->tcm_handle, handle, 0)) {
|
||||||
fprintf(stderr, "Illegal \"handle\"\n");
|
fprintf(stderr, "Illegal \"handle\"\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (slash) {
|
||||||
|
if (get_u32(&mask, slash+1, 0)) {
|
||||||
|
fprintf(stderr, "Illegal \"handle\" mask\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
addattr32(n, MAX_MSG, TCA_FW_MASK, mask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
tail = NLMSG_TAIL(n);
|
|
||||||
addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);
|
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (matches(*argv, "classid") == 0 ||
|
if (matches(*argv, "classid") == 0 ||
|
||||||
matches(*argv, "flowid") == 0) {
|
matches(*argv, "flowid") == 0) {
|
||||||
|
|
@ -111,8 +122,16 @@ static int fw_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u
|
||||||
|
|
||||||
parse_rtattr_nested(tb, TCA_FW_MAX, opt);
|
parse_rtattr_nested(tb, TCA_FW_MAX, opt);
|
||||||
|
|
||||||
if (handle)
|
if (handle || tb[TCA_FW_MASK]) {
|
||||||
fprintf(f, "handle 0x%x ", handle);
|
__u32 mark = 0, mask = 0;
|
||||||
|
if(handle)
|
||||||
|
mark = handle;
|
||||||
|
if(tb[TCA_FW_MASK] &&
|
||||||
|
(mask = *(__u32*)RTA_DATA(tb[TCA_FW_MASK])) != 0xFFFFFFFF)
|
||||||
|
fprintf(f, "handle 0x%x/0x%x ", mark, mask);
|
||||||
|
else
|
||||||
|
fprintf(f, "handle 0x%x ", handle);
|
||||||
|
}
|
||||||
|
|
||||||
if (tb[TCA_FW_CLASSID]) {
|
if (tb[TCA_FW_CLASSID]) {
|
||||||
SPRINT_BUF(b1);
|
SPRINT_BUF(b1);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,213 @@
|
||||||
|
/*
|
||||||
|
* m_nat.c NAT module
|
||||||
|
*
|
||||||
|
* This program is free software; you can distribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Authors: Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include "utils.h"
|
||||||
|
#include "tc_util.h"
|
||||||
|
#include <linux/tc_act/tc_nat.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
explain(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: ... nat NAT\n"
|
||||||
|
"NAT := DIRECTION OLD NEW\n"
|
||||||
|
"DIRECTION := { ingress | egress }\n"
|
||||||
|
"OLD := PREFIX\n"
|
||||||
|
"NEW := ADDRESS\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
explain();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_nat_args(int *argc_p, char ***argv_p,struct tc_nat *sel)
|
||||||
|
{
|
||||||
|
int argc = *argc_p;
|
||||||
|
char **argv = *argv_p;
|
||||||
|
inet_prefix addr;
|
||||||
|
|
||||||
|
if (argc <= 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (matches(*argv, "egress") == 0)
|
||||||
|
sel->flags |= TCA_NAT_FLAG_EGRESS;
|
||||||
|
else if (matches(*argv, "ingress") != 0)
|
||||||
|
goto bad_val;
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
|
if (get_prefix_1(&addr, *argv, AF_INET))
|
||||||
|
goto bad_val;
|
||||||
|
|
||||||
|
sel->old_addr = addr.data[0];
|
||||||
|
sel->mask = htonl(~0u << (32 - addr.bitlen));
|
||||||
|
|
||||||
|
NEXT_ARG();
|
||||||
|
|
||||||
|
if (get_prefix_1(&addr, *argv, AF_INET))
|
||||||
|
goto bad_val;
|
||||||
|
|
||||||
|
sel->new_addr = addr.data[0];
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
*argc_p = argc;
|
||||||
|
*argv_p = argv;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bad_val:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_nat(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
|
||||||
|
{
|
||||||
|
struct tc_nat sel;
|
||||||
|
|
||||||
|
int argc = *argc_p;
|
||||||
|
char **argv = *argv_p;
|
||||||
|
int ok = 0;
|
||||||
|
struct rtattr *tail;
|
||||||
|
|
||||||
|
memset(&sel, 0, sizeof(sel));
|
||||||
|
|
||||||
|
while (argc > 0) {
|
||||||
|
if (matches(*argv, "nat") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (parse_nat_args(&argc, &argv, &sel)) {
|
||||||
|
fprintf(stderr, "Illegal nat construct (%s) \n",
|
||||||
|
*argv);
|
||||||
|
explain();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ok++;
|
||||||
|
continue;
|
||||||
|
} else if (matches(*argv, "help") == 0) {
|
||||||
|
usage();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
explain();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc) {
|
||||||
|
if (matches(*argv, "reclassify") == 0) {
|
||||||
|
sel.action = TC_ACT_RECLASSIFY;
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
} else if (matches(*argv, "pipe") == 0) {
|
||||||
|
sel.action = TC_ACT_PIPE;
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
} else if (matches(*argv, "drop") == 0 ||
|
||||||
|
matches(*argv, "shot") == 0) {
|
||||||
|
sel.action = TC_ACT_SHOT;
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
} else if (matches(*argv, "continue") == 0) {
|
||||||
|
sel.action = TC_ACT_UNSPEC;
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
} else if (matches(*argv, "pass") == 0) {
|
||||||
|
sel.action = TC_ACT_OK;
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc) {
|
||||||
|
if (matches(*argv, "index") == 0) {
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&sel.index, *argv, 10)) {
|
||||||
|
fprintf(stderr, "Pedit: Illegal \"index\"\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tail = NLMSG_TAIL(n);
|
||||||
|
addattr_l(n, MAX_MSG, tca_id, NULL, 0);
|
||||||
|
addattr_l(n, MAX_MSG, TCA_NAT_PARMS, &sel, sizeof(sel));
|
||||||
|
tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
|
||||||
|
|
||||||
|
*argc_p = argc;
|
||||||
|
*argv_p = argv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
print_nat(struct action_util *au,FILE * f, struct rtattr *arg)
|
||||||
|
{
|
||||||
|
struct tc_nat *sel;
|
||||||
|
struct rtattr *tb[TCA_NAT_MAX + 1];
|
||||||
|
char buf1[256];
|
||||||
|
char buf2[256];
|
||||||
|
SPRINT_BUF(buf3);
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (arg == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
parse_rtattr_nested(tb, TCA_NAT_MAX, arg);
|
||||||
|
|
||||||
|
if (tb[TCA_NAT_PARMS] == NULL) {
|
||||||
|
fprintf(f, "[NULL nat parameters]");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sel = RTA_DATA(tb[TCA_NAT_PARMS]);
|
||||||
|
|
||||||
|
len = ffs(sel->mask);
|
||||||
|
len = len ? 33 - len : 0;
|
||||||
|
|
||||||
|
fprintf(f, " nat %s %s/%d %s %s", sel->flags & TCA_NAT_FLAG_EGRESS ?
|
||||||
|
"egress" : "ingress",
|
||||||
|
format_host(AF_INET, 4, &sel->old_addr, buf1, sizeof(buf1)),
|
||||||
|
len,
|
||||||
|
format_host(AF_INET, 4, &sel->new_addr, buf2, sizeof(buf2)),
|
||||||
|
action_n2a(sel->action, buf3, sizeof (buf3)));
|
||||||
|
|
||||||
|
if (show_stats) {
|
||||||
|
if (tb[TCA_NAT_TM]) {
|
||||||
|
struct tcf_t *tm = RTA_DATA(tb[TCA_NAT_TM]);
|
||||||
|
print_tm(f,tm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct action_util nat_action_util = {
|
||||||
|
.id = "nat",
|
||||||
|
.parse_aopt = parse_nat,
|
||||||
|
.print_aopt = print_nat,
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue