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
|
||||
\begin{NB}
|
||||
The {\tt ip} utility does not change the \verb|PROMISC|
|
||||
or \verb|ALLMULTI| flags. These flags are considered
|
||||
obsolete and should not be changed administratively.
|
||||
The \verb|PROMISC| and \verb|ALLMULTI| flags are considered
|
||||
obsolete and should not be changed administratively, though
|
||||
the {\tt ip} utility will allow that.
|
||||
\end{NB}
|
||||
|
||||
\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
|
||||
them here.
|
||||
\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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
return parse_rtattr_nested(tb, max, rta);
|
||||
}
|
||||
memset(tb, 0, sizeof(struct rtattr *) * max);
|
||||
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
unsigned long res;
|
||||
|
|
@ -304,7 +346,8 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)
|
|||
dst->bitlen = 32;
|
||||
}
|
||||
if (slash) {
|
||||
if (get_unsigned(&plen, slash+1, 0) || plen > dst->bitlen) {
|
||||
if (get_netmask(&plen, slash+1, 0)
|
||||
|| plen > dst->bitlen) {
|
||||
err = -1;
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ TCMODULES += q_htb.o
|
|||
TCMODULES += m_gact.o
|
||||
TCMODULES += m_mirred.o
|
||||
TCMODULES += m_ipt.o
|
||||
TCMODULES += m_nat.o
|
||||
TCMODULES += m_pedit.o
|
||||
TCMODULES += p_ip.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));
|
||||
|
||||
tail = NLMSG_TAIL(n);
|
||||
addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);
|
||||
|
||||
if (handle) {
|
||||
char *slash;
|
||||
__u32 mask = 0;
|
||||
if ((slash = strchr(handle, '/')) != NULL)
|
||||
*slash = '\0';
|
||||
if (get_u32(&t->tcm_handle, handle, 0)) {
|
||||
fprintf(stderr, "Illegal \"handle\"\n");
|
||||
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)
|
||||
return 0;
|
||||
|
||||
tail = NLMSG_TAIL(n);
|
||||
addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);
|
||||
|
||||
while (argc > 0) {
|
||||
if (matches(*argv, "classid") == 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);
|
||||
|
||||
if (handle)
|
||||
fprintf(f, "handle 0x%x ", handle);
|
||||
if (handle || tb[TCA_FW_MASK]) {
|
||||
__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]) {
|
||||
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