~ubuntu-branches/ubuntu/precise/iproute/precise

« back to all changes in this revision

Viewing changes to ip/ipntable.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2006-11-14 15:18:53 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20061114151853-nd3k7f6d10e18r7m
Tags: 20061002-2ubuntu1
Merge from debian unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C)2006 USAGI/WIDE Project
 
3
 * 
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 * 
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 * 
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 */
 
18
/*
 
19
 * based on ipneigh.c
 
20
 */
 
21
/*
 
22
 * Authors:
 
23
 *      Masahide NAKAMURA @USAGI
 
24
 */
 
25
 
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#include <sys/time.h>
 
30
#include <time.h>
 
31
 
 
32
#include "utils.h"
 
33
#include "ip_common.h"
 
34
 
 
35
static struct
 
36
{
 
37
        int family;
 
38
        int index;
 
39
#define NONE_DEV        (-1)
 
40
        char name[1024];
 
41
} filter;
 
42
 
 
43
static void usage(void) __attribute__((noreturn));
 
44
 
 
45
static void usage(void)
 
46
{
 
47
        fprintf(stderr,
 
48
                "Usage: ip ntable change name NAME [ dev DEV ]\n"
 
49
                "          [ thresh1 VAL ] [ thresh2 VAL ] [ thresh3 VAL ] [ gc_int MSEC ]\n"
 
50
                "          [ PARMS ]\n"
 
51
                "Usage: ip ntable show [ dev DEV ] [ name NAME ]\n"
 
52
 
 
53
                "PARMS := [ base_reachable MSEC ] [ retrans MSEC ] [ gc_stale MSEC ]\n"
 
54
                "         [ delay_probe MSEC ] [ queue LEN ]\n"
 
55
                "         [ app_probs VAL ] [ ucast_probes VAL ] [ mcast_probes VAL ]\n"
 
56
                "         [ anycast_delay MSEC ] [ proxy_delay MSEC ] [ proxy_queue LEN ]\n"
 
57
                "         [ locktime MSEC ]\n"
 
58
                );
 
59
 
 
60
        exit(-1);
 
61
}
 
62
 
 
63
static int ipntable_modify(int cmd, int flags, int argc, char **argv)
 
64
{
 
65
        struct {
 
66
                struct nlmsghdr         n;
 
67
                struct ndtmsg           ndtm;
 
68
                char                    buf[1024];
 
69
        } req;
 
70
        char *namep = NULL;
 
71
        char *threshsp = NULL;
 
72
        char *gc_intp = NULL;
 
73
        char parms_buf[1024];
 
74
        struct rtattr *parms_rta = (struct rtattr *)parms_buf;
 
75
        int parms_change = 0;
 
76
 
 
77
        memset(&req, 0, sizeof(req));
 
78
 
 
79
        req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndtmsg));
 
80
        req.n.nlmsg_flags = NLM_F_REQUEST|flags;
 
81
        req.n.nlmsg_type = cmd;
 
82
 
 
83
        req.ndtm.ndtm_family = preferred_family;
 
84
        req.ndtm.ndtm_pad1 = 0;
 
85
        req.ndtm.ndtm_pad2 = 0;
 
86
 
 
87
        memset(&parms_buf, 0, sizeof(parms_buf));
 
88
 
 
89
        parms_rta->rta_type = NDTA_PARMS;
 
90
        parms_rta->rta_len = RTA_LENGTH(0);
 
91
 
 
92
        while (argc > 0) {
 
93
                if (strcmp(*argv, "name") == 0) {
 
94
                        int len;
 
95
 
 
96
                        NEXT_ARG();
 
97
                        if (namep)
 
98
                                duparg("NAME", *argv);
 
99
 
 
100
                        namep = *argv;
 
101
                        len = strlen(namep) + 1;
 
102
                        addattr_l(&req.n, sizeof(req), NDTA_NAME, namep, len);
 
103
                } else if (strcmp(*argv, "thresh1") == 0) {
 
104
                        __u32 thresh1;
 
105
 
 
106
                        NEXT_ARG();
 
107
                        threshsp = *argv;
 
108
 
 
109
                        if (get_u32(&thresh1, *argv, 0))
 
110
                                invarg("\"thresh1\" value is invalid", *argv);
 
111
 
 
112
                        addattr32(&req.n, sizeof(req), NDTA_THRESH1, thresh1);
 
113
                } else if (strcmp(*argv, "thresh2") == 0) {
 
114
                        __u32 thresh2;
 
115
 
 
116
                        NEXT_ARG();
 
117
                        threshsp = *argv;
 
118
 
 
119
                        if (get_u32(&thresh2, *argv, 0))
 
120
                                invarg("\"thresh2\" value is invalid", *argv);
 
121
 
 
122
                        addattr32(&req.n, sizeof(req), NDTA_THRESH2, thresh2);
 
123
                } else if (strcmp(*argv, "thresh3") == 0) {
 
124
                        __u32 thresh3;
 
125
 
 
126
                        NEXT_ARG();
 
127
                        threshsp = *argv;
 
128
 
 
129
                        if (get_u32(&thresh3, *argv, 0))
 
130
                                invarg("\"thresh3\" value is invalid", *argv);
 
131
 
 
132
                        addattr32(&req.n, sizeof(req), NDTA_THRESH3, thresh3);
 
133
                } else if (strcmp(*argv, "gc_int") == 0) {
 
134
                        __u64 gc_int;
 
135
 
 
136
                        NEXT_ARG();
 
137
                        gc_intp = *argv;
 
138
 
 
139
                        if (get_u64(&gc_int, *argv, 0))
 
140
                                invarg("\"gc_int\" value is invalid", *argv);
 
141
 
 
142
                        addattr_l(&req.n, sizeof(req), NDTA_GC_INTERVAL,
 
143
                                  &gc_int, sizeof(gc_int));
 
144
                } else if (strcmp(*argv, "dev") == 0) {
 
145
                        __u32 ifindex;
 
146
 
 
147
                        NEXT_ARG();
 
148
                        ifindex = ll_name_to_index(*argv);
 
149
                        if (ifindex == 0) {
 
150
                                fprintf(stderr, "Cannot find device \"%s\"\n", *argv);
 
151
                                return -1;
 
152
                        }
 
153
 
 
154
                        rta_addattr32(parms_rta, sizeof(parms_buf),
 
155
                                      NDTPA_IFINDEX, ifindex);
 
156
                } else if (strcmp(*argv, "base_reachable") == 0) {
 
157
                        __u64 breachable;
 
158
 
 
159
                        NEXT_ARG();
 
160
 
 
161
                        if (get_u64(&breachable, *argv, 0))
 
162
                                invarg("\"base_reachable\" value is invalid", *argv);
 
163
 
 
164
                        rta_addattr_l(parms_rta, sizeof(parms_buf),
 
165
                                      NDTPA_BASE_REACHABLE_TIME,
 
166
                                      &breachable, sizeof(breachable));
 
167
                        parms_change = 1;
 
168
                } else if (strcmp(*argv, "retrans") == 0) {
 
169
                        __u64 retrans;
 
170
 
 
171
                        NEXT_ARG();
 
172
 
 
173
                        if (get_u64(&retrans, *argv, 0))
 
174
                                invarg("\"retrans\" value is invalid", *argv);
 
175
 
 
176
                        rta_addattr_l(parms_rta, sizeof(parms_buf),
 
177
                                      NDTPA_RETRANS_TIME,
 
178
                                      &retrans, sizeof(retrans));
 
179
                        parms_change = 1;
 
180
                } else if (strcmp(*argv, "gc_stale") == 0) {
 
181
                        __u64 gc_stale;
 
182
 
 
183
                        NEXT_ARG();
 
184
 
 
185
                        if (get_u64(&gc_stale, *argv, 0))
 
186
                                invarg("\"gc_stale\" value is invalid", *argv);
 
187
 
 
188
                        rta_addattr_l(parms_rta, sizeof(parms_buf),
 
189
                                      NDTPA_GC_STALETIME,
 
190
                                      &gc_stale, sizeof(gc_stale));
 
191
                        parms_change = 1;
 
192
                } else if (strcmp(*argv, "delay_probe") == 0) {
 
193
                        __u64 delay_probe;
 
194
 
 
195
                        NEXT_ARG();
 
196
 
 
197
                        if (get_u64(&delay_probe, *argv, 0))
 
198
                                invarg("\"delay_probe\" value is invalid", *argv);
 
199
 
 
200
                        rta_addattr_l(parms_rta, sizeof(parms_buf),
 
201
                                      NDTPA_DELAY_PROBE_TIME,
 
202
                                      &delay_probe, sizeof(delay_probe));
 
203
                        parms_change = 1;
 
204
                } else if (strcmp(*argv, "queue") == 0) {
 
205
                        __u32 queue;
 
206
 
 
207
                        NEXT_ARG();
 
208
 
 
209
                        if (get_u32(&queue, *argv, 0))
 
210
                                invarg("\"queue\" value is invalid", *argv);
 
211
 
 
212
                        if (!parms_rta)
 
213
                                parms_rta = (struct rtattr *)&parms_buf;
 
214
                        rta_addattr32(parms_rta, sizeof(parms_buf),
 
215
                                      NDTPA_QUEUE_LEN, queue);
 
216
                        parms_change = 1;
 
217
                } else if (strcmp(*argv, "app_probes") == 0) {
 
218
                        __u32 aprobe;
 
219
 
 
220
                        NEXT_ARG();
 
221
 
 
222
                        if (get_u32(&aprobe, *argv, 0))
 
223
                                invarg("\"app_probes\" value is invalid", *argv);
 
224
 
 
225
                        rta_addattr32(parms_rta, sizeof(parms_buf),
 
226
                                      NDTPA_APP_PROBES, aprobe);
 
227
                        parms_change = 1;
 
228
                } else if (strcmp(*argv, "ucast_probes") == 0) {
 
229
                        __u32 uprobe;
 
230
 
 
231
                        NEXT_ARG();
 
232
 
 
233
                        if (get_u32(&uprobe, *argv, 0))
 
234
                                invarg("\"ucast_probes\" value is invalid", *argv);
 
235
 
 
236
                        rta_addattr32(parms_rta, sizeof(parms_buf),
 
237
                                      NDTPA_UCAST_PROBES, uprobe);
 
238
                        parms_change = 1;
 
239
                } else if (strcmp(*argv, "mcast_probes") == 0) {
 
240
                        __u32 mprobe;
 
241
 
 
242
                        NEXT_ARG();
 
243
 
 
244
                        if (get_u32(&mprobe, *argv, 0))
 
245
                                invarg("\"mcast_probes\" value is invalid", *argv);
 
246
 
 
247
                        rta_addattr32(parms_rta, sizeof(parms_buf),
 
248
                                      NDTPA_MCAST_PROBES, mprobe);
 
249
                        parms_change = 1;
 
250
                } else if (strcmp(*argv, "anycast_delay") == 0) {
 
251
                        __u64 anycast_delay;
 
252
 
 
253
                        NEXT_ARG();
 
254
 
 
255
                        if (get_u64(&anycast_delay, *argv, 0))
 
256
                                invarg("\"anycast_delay\" value is invalid", *argv);
 
257
 
 
258
                        rta_addattr_l(parms_rta, sizeof(parms_buf),
 
259
                                      NDTPA_ANYCAST_DELAY,
 
260
                                      &anycast_delay, sizeof(anycast_delay));
 
261
                        parms_change = 1;
 
262
                } else if (strcmp(*argv, "proxy_delay") == 0) {
 
263
                        __u64 proxy_delay;
 
264
 
 
265
                        NEXT_ARG();
 
266
 
 
267
                        if (get_u64(&proxy_delay, *argv, 0))
 
268
                                invarg("\"proxy_delay\" value is invalid", *argv);
 
269
 
 
270
                        rta_addattr_l(parms_rta, sizeof(parms_buf),
 
271
                                      NDTPA_PROXY_DELAY,
 
272
                                      &proxy_delay, sizeof(proxy_delay));
 
273
                        parms_change = 1;
 
274
                } else if (strcmp(*argv, "proxy_queue") == 0) {
 
275
                        __u32 pqueue;
 
276
 
 
277
                        NEXT_ARG();
 
278
 
 
279
                        if (get_u32(&pqueue, *argv, 0))
 
280
                                invarg("\"proxy_queue\" value is invalid", *argv);
 
281
 
 
282
                        rta_addattr32(parms_rta, sizeof(parms_buf),
 
283
                                      NDTPA_PROXY_QLEN, pqueue);
 
284
                        parms_change = 1;
 
285
                } else if (strcmp(*argv, "locktime") == 0) {
 
286
                        __u64 locktime;
 
287
 
 
288
                        NEXT_ARG();
 
289
 
 
290
                        if (get_u64(&locktime, *argv, 0))
 
291
                                invarg("\"locktime\" value is invalid", *argv);
 
292
 
 
293
                        rta_addattr_l(parms_rta, sizeof(parms_buf),
 
294
                                      NDTPA_LOCKTIME,
 
295
                                      &locktime, sizeof(locktime));
 
296
                        parms_change = 1;
 
297
                } else {
 
298
                        invarg("unknown", *argv);
 
299
                }
 
300
 
 
301
                argc--; argv++;
 
302
        }
 
303
 
 
304
        if (!namep)
 
305
                missarg("NAME");
 
306
        if (!threshsp && !gc_intp && !parms_change) {
 
307
                fprintf(stderr, "Not enough information: changable attributes required.\n");
 
308
                exit(-1);
 
309
        }
 
310
 
 
311
        if (parms_rta->rta_len > RTA_LENGTH(0)) {
 
312
                addattr_l(&req.n, sizeof(req), NDTA_PARMS, RTA_DATA(parms_rta),
 
313
                          RTA_PAYLOAD(parms_rta));
 
314
        }
 
315
 
 
316
        if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
 
317
                exit(2);
 
318
 
 
319
        return 0;
 
320
}
 
321
 
 
322
static const char *ntable_strtime_delta(__u32 msec)
 
323
{
 
324
        static char str[32];
 
325
        struct timeval now;
 
326
        time_t t;
 
327
        struct tm *tp;
 
328
 
 
329
        if (msec == 0)
 
330
                goto error;
 
331
 
 
332
        memset(&now, 0, sizeof(now));
 
333
 
 
334
        if (gettimeofday(&now, NULL) < 0) {
 
335
                perror("gettimeofday");
 
336
                goto error;
 
337
        }
 
338
 
 
339
        t = now.tv_sec - (msec / 1000);
 
340
        tp = localtime(&t);
 
341
        if (!tp)
 
342
                goto error;
 
343
 
 
344
        strftime(str, sizeof(str), "%Y-%m-%d %T", tp);
 
345
 
 
346
        return str;
 
347
 error:
 
348
        strcpy(str, "(error)");
 
349
        return str;
 
350
}
 
351
 
 
352
int print_ntable(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 
353
{
 
354
        FILE *fp = (FILE*)arg;
 
355
        struct ndtmsg *ndtm = NLMSG_DATA(n);
 
356
        int len = n->nlmsg_len;
 
357
        struct rtattr *tb[NDTA_MAX+1];
 
358
        struct rtattr *tpb[NDTPA_MAX+1];
 
359
        int ret;
 
360
 
 
361
        if (n->nlmsg_type != RTM_NEWNEIGHTBL) {
 
362
                fprintf(stderr, "Not NEIGHTBL: %08x %08x %08x\n",
 
363
                        n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
 
364
                return 0;
 
365
        }
 
366
        len -= NLMSG_LENGTH(sizeof(*ndtm));
 
367
        if (len < 0) {
 
368
                fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
 
369
                return -1;
 
370
        }
 
371
 
 
372
        if (preferred_family && preferred_family != ndtm->ndtm_family)
 
373
                return 0;
 
374
 
 
375
        parse_rtattr(tb, NDTA_MAX, NDTA_RTA(ndtm),
 
376
                     n->nlmsg_len - NLMSG_LENGTH(sizeof(*ndtm)));
 
377
 
 
378
        if (tb[NDTA_NAME]) {
 
379
                char *name = RTA_DATA(tb[NDTA_NAME]);
 
380
 
 
381
                if (strlen(filter.name) > 0 && strcmp(filter.name, name))
 
382
                        return 0;
 
383
        }
 
384
        if (tb[NDTA_PARMS]) {
 
385
                parse_rtattr(tpb, NDTPA_MAX, RTA_DATA(tb[NDTA_PARMS]),
 
386
                             RTA_PAYLOAD(tb[NDTA_PARMS]));
 
387
 
 
388
                if (tpb[NDTPA_IFINDEX]) {
 
389
                        __u32 ifindex = *(__u32 *)RTA_DATA(tpb[NDTPA_IFINDEX]);
 
390
 
 
391
                        if (filter.index && filter.index != ifindex)
 
392
                                return 0;
 
393
                } else {
 
394
                        if (filter.index && filter.index != NONE_DEV)
 
395
                                return 0;
 
396
                }
 
397
        }
 
398
 
 
399
        if (ndtm->ndtm_family == AF_INET)
 
400
                fprintf(fp, "inet ");
 
401
        else if (ndtm->ndtm_family == AF_INET6)
 
402
                fprintf(fp, "inet6 ");
 
403
        else if (ndtm->ndtm_family == AF_DECnet)
 
404
                fprintf(fp, "dnet ");
 
405
        else
 
406
                fprintf(fp, "(%d) ", ndtm->ndtm_family);
 
407
 
 
408
        if (tb[NDTA_NAME]) {
 
409
                char *name = RTA_DATA(tb[NDTA_NAME]);
 
410
                fprintf(fp, "%s ", name);
 
411
        }
 
412
 
 
413
        fprintf(fp, "%s", _SL_);
 
414
 
 
415
        ret = (tb[NDTA_THRESH1] || tb[NDTA_THRESH2] || tb[NDTA_THRESH3] ||
 
416
               tb[NDTA_GC_INTERVAL]);
 
417
        if (ret)
 
418
                fprintf(fp, "    ");
 
419
 
 
420
        if (tb[NDTA_THRESH1]) {
 
421
                __u32 thresh1 = *(__u32 *)RTA_DATA(tb[NDTA_THRESH1]);
 
422
                fprintf(fp, "thresh1 %u ", thresh1);
 
423
        }
 
424
        if (tb[NDTA_THRESH2]) {
 
425
                __u32 thresh2 = *(__u32 *)RTA_DATA(tb[NDTA_THRESH2]);
 
426
                fprintf(fp, "thresh2 %u ", thresh2);
 
427
        }
 
428
        if (tb[NDTA_THRESH3]) {
 
429
                __u32 thresh3 = *(__u32 *)RTA_DATA(tb[NDTA_THRESH3]);
 
430
                fprintf(fp, "thresh3 %u ", thresh3);
 
431
        }
 
432
        if (tb[NDTA_GC_INTERVAL]) {
 
433
                __u64 gc_int = *(__u64 *)RTA_DATA(tb[NDTA_GC_INTERVAL]);
 
434
                fprintf(fp, "gc_int %llu ", gc_int);
 
435
        }
 
436
 
 
437
        if (ret)
 
438
                fprintf(fp, "%s", _SL_);
 
439
 
 
440
        if (tb[NDTA_CONFIG] && show_stats) {
 
441
                struct ndt_config *ndtc = RTA_DATA(tb[NDTA_CONFIG]);
 
442
 
 
443
                fprintf(fp, "    ");
 
444
                fprintf(fp, "config ");
 
445
 
 
446
                fprintf(fp, "key_len %u ", ndtc->ndtc_key_len);
 
447
                fprintf(fp, "entry_size %u ", ndtc->ndtc_entry_size);
 
448
                fprintf(fp, "entries %u ", ndtc->ndtc_entries);
 
449
 
 
450
                fprintf(fp, "%s", _SL_);
 
451
                fprintf(fp, "        ");
 
452
 
 
453
                fprintf(fp, "last_flush %s ",
 
454
                        ntable_strtime_delta(ndtc->ndtc_last_flush));
 
455
                fprintf(fp, "last_rand %s ",
 
456
                        ntable_strtime_delta(ndtc->ndtc_last_rand));
 
457
 
 
458
                fprintf(fp, "%s", _SL_);
 
459
                fprintf(fp, "        ");
 
460
 
 
461
                fprintf(fp, "hash_rnd %u ", ndtc->ndtc_hash_rnd);
 
462
                fprintf(fp, "hash_mask %08x ", ndtc->ndtc_hash_mask);
 
463
 
 
464
                fprintf(fp, "hash_chain_gc %u ", ndtc->ndtc_hash_chain_gc);
 
465
                fprintf(fp, "proxy_qlen %u ", ndtc->ndtc_proxy_qlen);
 
466
 
 
467
                fprintf(fp, "%s", _SL_);
 
468
        }
 
469
 
 
470
        if (tb[NDTA_PARMS]) {
 
471
                if (tpb[NDTPA_IFINDEX]) {
 
472
                        __u32 ifindex = *(__u32 *)RTA_DATA(tpb[NDTPA_IFINDEX]);
 
473
 
 
474
                        fprintf(fp, "    ");
 
475
                        fprintf(fp, "dev %s ", ll_index_to_name(ifindex));
 
476
                        fprintf(fp, "%s", _SL_);
 
477
                }
 
478
 
 
479
                fprintf(fp, "    ");
 
480
 
 
481
                if (tpb[NDTPA_REFCNT]) {
 
482
                        __u32 refcnt = *(__u32 *)RTA_DATA(tpb[NDTPA_REFCNT]);
 
483
                        fprintf(fp, "refcnt %u ", refcnt);
 
484
                }
 
485
                if (tpb[NDTPA_REACHABLE_TIME]) {
 
486
                        __u64 reachable = *(__u64 *)RTA_DATA(tpb[NDTPA_REACHABLE_TIME]);
 
487
                        fprintf(fp, "reachable %llu ", reachable);
 
488
                }
 
489
                if (tpb[NDTPA_BASE_REACHABLE_TIME]) {
 
490
                        __u64 breachable = *(__u64 *)RTA_DATA(tpb[NDTPA_BASE_REACHABLE_TIME]);
 
491
                        fprintf(fp, "base_reachable %llu ", breachable);
 
492
                }
 
493
                if (tpb[NDTPA_RETRANS_TIME]) {
 
494
                        __u64 retrans = *(__u64 *)RTA_DATA(tpb[NDTPA_RETRANS_TIME]);
 
495
                        fprintf(fp, "retrans %llu ", retrans);
 
496
                }
 
497
 
 
498
                fprintf(fp, "%s", _SL_);
 
499
 
 
500
                fprintf(fp, "    ");
 
501
 
 
502
                if (tpb[NDTPA_GC_STALETIME]) {
 
503
                        __u64 gc_stale = *(__u64 *)RTA_DATA(tpb[NDTPA_GC_STALETIME]);
 
504
                        fprintf(fp, "gc_stale %llu ", gc_stale);
 
505
                }
 
506
                if (tpb[NDTPA_DELAY_PROBE_TIME]) {
 
507
                        __u64 delay_probe = *(__u64 *)RTA_DATA(tpb[NDTPA_DELAY_PROBE_TIME]);
 
508
                        fprintf(fp, "delay_probe %llu ", delay_probe);
 
509
                }
 
510
                if (tpb[NDTPA_QUEUE_LEN]) {
 
511
                        __u32 queue = *(__u32 *)RTA_DATA(tpb[NDTPA_QUEUE_LEN]);
 
512
                        fprintf(fp, "queue %u ", queue);
 
513
                }
 
514
 
 
515
                fprintf(fp, "%s", _SL_);
 
516
 
 
517
                fprintf(fp, "    ");
 
518
 
 
519
                if (tpb[NDTPA_APP_PROBES]) {
 
520
                        __u32 aprobe = *(__u32 *)RTA_DATA(tpb[NDTPA_APP_PROBES]);
 
521
                        fprintf(fp, "app_probes %u ", aprobe);
 
522
                }
 
523
                if (tpb[NDTPA_UCAST_PROBES]) {
 
524
                        __u32 uprobe = *(__u32 *)RTA_DATA(tpb[NDTPA_UCAST_PROBES]);
 
525
                        fprintf(fp, "ucast_probes %u ", uprobe);
 
526
                }
 
527
                if (tpb[NDTPA_MCAST_PROBES]) {
 
528
                        __u32 mprobe = *(__u32 *)RTA_DATA(tpb[NDTPA_MCAST_PROBES]);
 
529
                        fprintf(fp, "mcast_probes %u ", mprobe);
 
530
                }
 
531
 
 
532
                fprintf(fp, "%s", _SL_);
 
533
 
 
534
                fprintf(fp, "    ");
 
535
 
 
536
                if (tpb[NDTPA_ANYCAST_DELAY]) {
 
537
                        __u64 anycast_delay = *(__u64 *)RTA_DATA(tpb[NDTPA_ANYCAST_DELAY]);
 
538
                        fprintf(fp, "anycast_delay %llu ", anycast_delay);
 
539
                }
 
540
                if (tpb[NDTPA_PROXY_DELAY]) {
 
541
                        __u64 proxy_delay = *(__u64 *)RTA_DATA(tpb[NDTPA_PROXY_DELAY]);
 
542
                        fprintf(fp, "proxy_delay %llu ", proxy_delay);
 
543
                }
 
544
                if (tpb[NDTPA_PROXY_QLEN]) {
 
545
                        __u32 pqueue = *(__u32 *)RTA_DATA(tpb[NDTPA_PROXY_QLEN]);
 
546
                        fprintf(fp, "proxy_queue %u ", pqueue);
 
547
                }
 
548
                if (tpb[NDTPA_LOCKTIME]) {
 
549
                        __u64 locktime = *(__u64 *)RTA_DATA(tpb[NDTPA_LOCKTIME]);
 
550
                        fprintf(fp, "locktime %llu ", locktime);
 
551
                }
 
552
 
 
553
                fprintf(fp, "%s", _SL_);
 
554
        }
 
555
 
 
556
        if (tb[NDTA_STATS] && show_stats) {
 
557
                struct ndt_stats *ndts = RTA_DATA(tb[NDTA_STATS]);
 
558
 
 
559
                fprintf(fp, "    ");
 
560
                fprintf(fp, "stats ");
 
561
 
 
562
                fprintf(fp, "allocs %llu ", ndts->ndts_allocs);
 
563
                fprintf(fp, "destroys %llu ", ndts->ndts_destroys);
 
564
                fprintf(fp, "hash_grows %llu ", ndts->ndts_hash_grows);
 
565
 
 
566
                fprintf(fp, "%s", _SL_);
 
567
                fprintf(fp, "        ");
 
568
 
 
569
                fprintf(fp, "res_failed %llu ", ndts->ndts_res_failed);
 
570
                fprintf(fp, "lookups %llu ", ndts->ndts_lookups);
 
571
                fprintf(fp, "hits %llu ", ndts->ndts_hits);
 
572
 
 
573
                fprintf(fp, "%s", _SL_);
 
574
                fprintf(fp, "        ");
 
575
 
 
576
                fprintf(fp, "rcv_probes_mcast %llu ", ndts->ndts_rcv_probes_mcast);
 
577
                fprintf(fp, "rcv_probes_ucast %llu ", ndts->ndts_rcv_probes_ucast);
 
578
 
 
579
                fprintf(fp, "%s", _SL_);
 
580
                fprintf(fp, "        ");
 
581
 
 
582
                fprintf(fp, "periodic_gc_runs %llu ", ndts->ndts_periodic_gc_runs);
 
583
                fprintf(fp, "forced_gc_runs %llu ", ndts->ndts_forced_gc_runs);
 
584
 
 
585
                fprintf(fp, "%s", _SL_);
 
586
        }
 
587
 
 
588
        fprintf(fp, "\n");
 
589
 
 
590
        fflush(fp);
 
591
        return 0;
 
592
}
 
593
 
 
594
void ipntable_reset_filter(void)
 
595
{
 
596
        memset(&filter, 0, sizeof(filter));
 
597
}
 
598
 
 
599
static int ipntable_show(int argc, char **argv)
 
600
{
 
601
        ipntable_reset_filter();
 
602
 
 
603
        filter.family = preferred_family;
 
604
 
 
605
        while (argc > 0) {
 
606
                if (strcmp(*argv, "dev") == 0) {
 
607
                        NEXT_ARG();
 
608
 
 
609
                        if (strcmp("none", *argv) == 0)
 
610
                                filter.index = NONE_DEV;
 
611
                        else if ((filter.index = ll_name_to_index(*argv)) == 0)
 
612
                                invarg("\"DEV\" is invalid", *argv);
 
613
                } else if (strcmp(*argv, "name") == 0) {
 
614
                        NEXT_ARG();
 
615
 
 
616
                        strncpy(filter.name, *argv, sizeof(filter.name));
 
617
                } else
 
618
                        invarg("unknown", *argv);
 
619
 
 
620
                argc--; argv++;
 
621
        }
 
622
 
 
623
        if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETNEIGHTBL) < 0) {
 
624
                perror("Cannot send dump request");
 
625
                exit(1);
 
626
        }
 
627
 
 
628
        if (rtnl_dump_filter(&rth, print_ntable, stdout, NULL, NULL) < 0) {
 
629
                fprintf(stderr, "Dump terminated\n");
 
630
                exit(1);
 
631
        }
 
632
 
 
633
        return 0;
 
634
}
 
635
 
 
636
int do_ipntable(int argc, char **argv)
 
637
{
 
638
        ll_init_map(&rth);
 
639
 
 
640
        if (argc > 0) {
 
641
                if (matches(*argv, "change") == 0 ||
 
642
                    matches(*argv, "chg") == 0)
 
643
                        return ipntable_modify(RTM_SETNEIGHTBL,
 
644
                                               NLM_F_REPLACE,
 
645
                                               argc-1, argv+1);
 
646
                if (matches(*argv, "show") == 0 ||
 
647
                    matches(*argv, "lst") == 0 ||
 
648
                    matches(*argv, "list") == 0)
 
649
                        return ipntable_show(argc-1, argv+1);
 
650
                if (matches(*argv, "help") == 0)
 
651
                        usage();
 
652
        } else
 
653
                return ipntable_show(0, NULL);
 
654
 
 
655
        fprintf(stderr, "Command \"%s\" is unknown, try \"ip ntable help\".\n", *argv);
 
656
        exit(-1);
 
657
}