~ubuntu-branches/ubuntu/hardy/iproute/hardy-proposed

« back to all changes in this revision

Viewing changes to tc/m_mirred.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2006-07-06 10:23:46 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060706102346-tyd1mfjvay0nmz90
Tags: 20051007-4ubuntu1
* Merge from debian unstable, remaining changes:
  - versioned dependency on linux-kernel-headers,
  - MAX_ROUNDS patch to ip/ipaddress.c

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * m_egress.c           ingress/egress packet mirror/redir actions module 
 
3
 *
 
4
 *              This program is free software; you can distribute it and/or
 
5
 *              modify it under the terms of the GNU General Public License
 
6
 *              as published by the Free Software Foundation; either version
 
7
 *              2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * Authors:  J Hadi Salim (hadi@cyberus.ca) 
 
10
 * 
 
11
 * TODO: Add Ingress support
 
12
 *
 
13
 */
 
14
 
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
#include <unistd.h>
 
18
#include <syslog.h>
 
19
#include <fcntl.h>
 
20
#include <sys/socket.h>
 
21
#include <netinet/in.h>
 
22
#include <arpa/inet.h>
 
23
#include <string.h>
 
24
#include "utils.h"
 
25
#include "tc_util.h"
 
26
#include "tc_common.h"
 
27
#include <linux/tc_act/tc_mirred.h>
 
28
 
 
29
int mirred_d = 1;
 
30
 
 
31
static void
 
32
explain(void)
 
33
{
 
34
        fprintf(stderr, "Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME> \n");
 
35
        fprintf(stderr, "where: \n");
 
36
        fprintf(stderr, "DIRECTION := <ingress | egress>\n");
 
37
        fprintf(stderr, "aCTION := <mirror | redirect>\n");
 
38
        fprintf(stderr, "     : INDEX  is the specific policy instance id\n");
 
39
        fprintf(stderr, "     : DEVICENAME is the devicename \n");
 
40
}
 
41
 
 
42
#define usage() return(-1)
 
43
 
 
44
char *mirred_n2a(int action)
 
45
{
 
46
        switch (action) {
 
47
        case TCA_EGRESS_REDIR:
 
48
                return "Egress Redirect";
 
49
        case TCA_INGRESS_REDIR:
 
50
                return "Ingress Redirect";
 
51
        case TCA_EGRESS_MIRROR:
 
52
                return "Egress Mirror";
 
53
        case TCA_INGRESS_MIRROR:
 
54
                return "Ingress Mirror";
 
55
        default:
 
56
                return "unknown";
 
57
        }
 
58
}
 
59
 
 
60
int
 
61
parse_egress(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
 
62
{
 
63
 
 
64
        int argc = *argc_p;
 
65
        char **argv = *argv_p;
 
66
        int ok = 0, iok = 0, mirror=0,redir=0;
 
67
        struct tc_mirred p;
 
68
        struct rtattr *tail;
 
69
        char d[16];
 
70
 
 
71
        memset(d,0,sizeof(d)-1);
 
72
        memset(&p,0,sizeof(struct tc_mirred));
 
73
 
 
74
        while (argc > 0) {
 
75
 
 
76
                if (matches(*argv, "action") == 0) {
 
77
                        break;
 
78
                } else if (matches(*argv, "egress") == 0) {
 
79
                        NEXT_ARG();
 
80
                        ok++;
 
81
                        continue;
 
82
                } else {
 
83
 
 
84
                        if (matches(*argv, "index") == 0) {
 
85
                                NEXT_ARG();
 
86
                                if (get_u32(&p.index, *argv, 10)) {
 
87
                                        fprintf(stderr, "Illegal \"index\"\n");
 
88
                                        return -1;
 
89
                                }
 
90
                                iok++;
 
91
                                if (!ok) {
 
92
                                        argc--;
 
93
                                        argv++;
 
94
                                        break;
 
95
                                }
 
96
                        } else if(!ok) {
 
97
                                fprintf(stderr, "was expecting egress (%s)\n", *argv);
 
98
                                break;
 
99
 
 
100
                        } else if (!mirror && matches(*argv, "mirror") == 0) {
 
101
                                mirror=1;
 
102
                                if (redir) {
 
103
                                        fprintf(stderr, "Cant have both mirror and redir\n");
 
104
                                        return -1;
 
105
                                }
 
106
                                p.eaction = TCA_EGRESS_MIRROR;
 
107
                                p.action = TC_ACT_PIPE;
 
108
                                ok++;
 
109
                        } else if (!redir && matches(*argv, "redirect") == 0) {
 
110
                                redir=1;
 
111
                                if (mirror) {
 
112
                                        fprintf(stderr, "Cant have both mirror and redir\n");
 
113
                                        return -1;
 
114
                                }
 
115
                                p.eaction = TCA_EGRESS_REDIR;
 
116
                                p.action = TC_ACT_STOLEN;
 
117
                                ok++;
 
118
                        } else if ((redir || mirror) && matches(*argv, "dev") == 0) {
 
119
                                NEXT_ARG();
 
120
                                if (strlen(d))
 
121
                                        duparg("dev", *argv);
 
122
 
 
123
                                strncpy(d, *argv, sizeof(d)-1);
 
124
                                argc--;
 
125
                                argv++;
 
126
 
 
127
                                break;
 
128
 
 
129
                        }
 
130
                }
 
131
 
 
132
                NEXT_ARG();
 
133
        }
 
134
 
 
135
        if (!ok && !iok) {
 
136
                explain();
 
137
                return -1;
 
138
        }
 
139
 
 
140
 
 
141
 
 
142
        if (d[0])  {
 
143
                int idx;
 
144
                ll_init_map(&rth);
 
145
 
 
146
                if ((idx = ll_name_to_index(d)) == 0) {
 
147
                        fprintf(stderr, "Cannot find device \"%s\"\n", d);
 
148
                        return -1;
 
149
                }
 
150
 
 
151
                p.ifindex = idx;
 
152
        }
 
153
 
 
154
 
 
155
        if (argc && p.eaction == TCA_EGRESS_MIRROR) {
 
156
 
 
157
                if (matches(*argv, "reclassify") == 0) {
 
158
                        p.action = TC_POLICE_RECLASSIFY;
 
159
                        NEXT_ARG();
 
160
                } else if (matches(*argv, "pipe") == 0) {
 
161
                        p.action = TC_POLICE_PIPE;
 
162
                        NEXT_ARG();
 
163
                } else if (matches(*argv, "drop") == 0 ||
 
164
                           matches(*argv, "shot") == 0) {
 
165
                        p.action = TC_POLICE_SHOT;
 
166
                        NEXT_ARG();
 
167
                } else if (matches(*argv, "continue") == 0) {
 
168
                        p.action = TC_POLICE_UNSPEC;
 
169
                        NEXT_ARG();
 
170
                } else if (matches(*argv, "pass") == 0) {
 
171
                        p.action = TC_POLICE_OK;
 
172
                        NEXT_ARG();
 
173
                }
 
174
 
 
175
        }
 
176
 
 
177
        if (argc) {
 
178
                if (iok && matches(*argv, "index") == 0) {
 
179
                        fprintf(stderr, "mirred: Illegal double index\n");
 
180
                        return -1;
 
181
                } else {
 
182
                        if (matches(*argv, "index") == 0) {
 
183
                                NEXT_ARG();
 
184
                                if (get_u32(&p.index, *argv, 10)) {
 
185
                                        fprintf(stderr, "mirred: Illegal \"index\"\n");
 
186
                                        return -1;
 
187
                                }
 
188
                                argc--;
 
189
                                argv++;
 
190
                        }
 
191
                }
 
192
        }
 
193
 
 
194
        if (mirred_d)
 
195
                fprintf(stdout, "Action %d device %s ifindex %d\n",p.action, d,p.ifindex);
 
196
 
 
197
        tail = NLMSG_TAIL(n);
 
198
        addattr_l(n, MAX_MSG, tca_id, NULL, 0);
 
199
        addattr_l(n, MAX_MSG, TCA_MIRRED_PARMS, &p, sizeof (p));
 
200
        tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
 
201
 
 
202
        *argc_p = argc;
 
203
        *argv_p = argv;
 
204
        return 0;
 
205
}
 
206
 
 
207
 
 
208
int
 
209
parse_mirred(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
 
210
{
 
211
 
 
212
        int argc = *argc_p;
 
213
        char **argv = *argv_p;
 
214
 
 
215
        if (argc < 0) {
 
216
                fprintf(stderr,"mirred bad arguement count %d\n", argc);
 
217
                return -1;
 
218
        }
 
219
 
 
220
        if (matches(*argv, "mirred") == 0) {
 
221
                NEXT_ARG();
 
222
        } else {
 
223
                fprintf(stderr,"mirred bad arguement %s\n", *argv);
 
224
                return -1;
 
225
        }
 
226
 
 
227
 
 
228
        if (matches(*argv, "egress") == 0 || matches(*argv, "index") == 0) {
 
229
                int ret = parse_egress(a, &argc, &argv, tca_id, n);
 
230
                if (ret == 0) {
 
231
                        *argc_p = argc;
 
232
                        *argv_p = argv;
 
233
                        return 0;
 
234
                }
 
235
 
 
236
        } else if (matches(*argv, "ingress") == 0) {
 
237
                fprintf(stderr,"mirred ingress not supported at the moment\n");
 
238
 
 
239
        } else {
 
240
                fprintf(stderr,"mirred not supported %s\n", *argv);
 
241
        }
 
242
 
 
243
        return -1;
 
244
        
 
245
}
 
246
 
 
247
int
 
248
print_mirred(struct action_util *au,FILE * f, struct rtattr *arg)
 
249
{
 
250
        struct tc_mirred *p;
 
251
        struct rtattr *tb[TCA_MIRRED_MAX + 1];
 
252
        const char *dev;
 
253
        SPRINT_BUF(b1);
 
254
 
 
255
        if (arg == NULL)
 
256
                return -1;
 
257
 
 
258
        parse_rtattr_nested(tb, TCA_MIRRED_MAX, arg);
 
259
 
 
260
        if (tb[TCA_MIRRED_PARMS] == NULL) {
 
261
                fprintf(f, "[NULL mirred parameters]");
 
262
                return -1;
 
263
        }
 
264
        p = RTA_DATA(tb[TCA_MIRRED_PARMS]);
 
265
 
 
266
        /*
 
267
        ll_init_map(&rth);
 
268
        */
 
269
 
 
270
 
 
271
        if ((dev = ll_index_to_name(p->ifindex)) == 0) {
 
272
                fprintf(stderr, "Cannot find device %d\n", p->ifindex);
 
273
                return -1;
 
274
        }
 
275
 
 
276
        fprintf(f, "mirred (%s to device %s) %s", mirred_n2a(p->eaction), dev,action_n2a(p->action, b1, sizeof (b1)));
 
277
 
 
278
        fprintf(f, "\n ");
 
279
        fprintf(f, "\tindex %d ref %d bind %d",p->index,p->refcnt,p->bindcnt);
 
280
 
 
281
        if (show_stats) {
 
282
                if (tb[TCA_MIRRED_TM]) {
 
283
                        struct tcf_t *tm = RTA_DATA(tb[TCA_MIRRED_TM]);
 
284
                        print_tm(f,tm);
 
285
                }
 
286
        }
 
287
        fprintf(f, "\n ");
 
288
        return 0;
 
289
}
 
290
 
 
291
struct action_util mirred_action_util = {
 
292
        .id = "mirred",
 
293
        .parse_aopt = parse_mirred,
 
294
        .print_aopt = print_mirred,
 
295
};