Commit e50e9f91 authored by Stephen Hemminger's avatar Stephen Hemminger

Merge branch 'master' into net-2.6.25

parents 7ca30b78 4b270b17
......@@ -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
......
#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;
}
......@@ -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
......
......@@ -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);
......
/*
* 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,
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment