~ubuntu-branches/ubuntu/trusty/libnl3/trusty

« back to all changes in this revision

Viewing changes to lib/route/neigh.c

  • Committer: Bazaar Package Importer
  • Author(s): Heiko Stuebner
  • Date: 2011-05-21 19:25:13 UTC
  • Revision ID: james.westby@ubuntu.com-20110521192513-1ieyu9w9kym4bt16
Tags: upstream-3.0
ImportĀ upstreamĀ versionĀ 3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lib/route/neigh.c    Neighbours
 
3
 *
 
4
 *      This library is free software; you can redistribute it and/or
 
5
 *      modify it under the terms of the GNU Lesser General Public
 
6
 *      License as published by the Free Software Foundation version 2.1
 
7
 *      of the License.
 
8
 *
 
9
 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
 
10
 */
 
11
 
 
12
/**
 
13
 * @ingroup rtnl
 
14
 * @defgroup neigh Neighbours
 
15
 * @brief
 
16
 *
 
17
 * The neighbour table establishes bindings between protocol addresses and
 
18
 * link layer addresses for hosts sharing the same physical link. This
 
19
 * module allows you to access and manipulate the content of these tables.
 
20
 *
 
21
 * @par Neighbour States
 
22
 * @code
 
23
 * NUD_INCOMPLETE
 
24
 * NUD_REACHABLE
 
25
 * NUD_STALE
 
26
 * NUD_DELAY
 
27
 * NUD_PROBE
 
28
 * NUD_FAILED
 
29
 * NUD_NOARP
 
30
 * NUD_PERMANENT
 
31
 * @endcode
 
32
 *
 
33
 * @par Neighbour Flags
 
34
 * @code
 
35
 * NTF_USE
 
36
 * NTF_PROXY
 
37
 * NTF_ROUTER
 
38
 * @endcode
 
39
 *
 
40
 * @par Neighbour Identification
 
41
 * A neighbour is uniquely identified by the attributes listed below, whenever
 
42
 * you refer to an existing neighbour all of the attributes must be set.
 
43
 * Neighbours from caches automatically have all required attributes set.
 
44
 *   - interface index (rtnl_neigh_set_ifindex())
 
45
 *   - destination address (rtnl_neigh_set_dst())
 
46
 *
 
47
 * @par Changeable Attributes
 
48
 * \anchor neigh_changeable
 
49
 *  - state (rtnl_neigh_set_state())
 
50
 *  - link layer address (rtnl_neigh_set_lladdr())
 
51
 *
 
52
 * @par Required Caches for Dumping
 
53
 * In order to dump neighbour attributes you must provide the following
 
54
 * caches via nl_cache_provide()
 
55
 *  - link cache holding all links
 
56
 *
 
57
 * @par TODO
 
58
 *   - Document proxy settings
 
59
 *   - Document states and their influence
 
60
 *
 
61
 * @par 1) Retrieving information about configured neighbours
 
62
 * @code
 
63
 * // The first step is to retrieve a list of all available neighbour within
 
64
 * // the kernel and put them into a cache.
 
65
 * struct nl_cache *cache = rtnl_neigh_alloc_cache(sk);
 
66
 *
 
67
 * // Neighbours can then be looked up by the interface and destination
 
68
 * // address:
 
69
 * struct rtnl_neigh *neigh = rtnl_neigh_get(cache, ifindex, dst_addr);
 
70
 * 
 
71
 * // After successful usage, the object must be given back to the cache
 
72
 * rtnl_neigh_put(neigh);
 
73
 * @endcode
 
74
 *
 
75
 * @par 2) Adding new neighbours
 
76
 * @code
 
77
 * // Allocate an empty neighbour handle to be filled out with the attributes
 
78
 * // of the new neighbour.
 
79
 * struct rtnl_neigh *neigh = rtnl_neigh_alloc();
 
80
 *
 
81
 * // Fill out the attributes of the new neighbour
 
82
 * rtnl_neigh_set_ifindex(neigh, ifindex);
 
83
 * rtnl_neigh_set_dst(neigh, dst_addr);
 
84
 * rtnl_neigh_set_state(neigh, rtnl_neigh_str2state("permanent"));
 
85
 *
 
86
 * // Build the netlink message and send it to the kernel, the operation will
 
87
 * // block until the operation has been completed. Alternatively the required
 
88
 * // netlink message can be built using rtnl_neigh_build_add_request()
 
89
 * // to be sent out using nl_send_auto_complete().
 
90
 * rtnl_neigh_add(sk, neigh, NLM_F_CREATE);
 
91
 *
 
92
 * // Free the memory
 
93
 * rtnl_neigh_put(neigh);
 
94
 * @endcode
 
95
 *
 
96
 * @par 3) Deleting an existing neighbour
 
97
 * @code
 
98
 * // Allocate an empty neighbour object to be filled out with the attributes
 
99
 * // matching the neighbour to be deleted. Alternatively a fully equipped
 
100
 * // neighbour object out of a cache can be used instead.
 
101
 * struct rtnl_neigh *neigh = rtnl_neigh_alloc();
 
102
 *
 
103
 * // Neighbours are uniquely identified by their interface index and
 
104
 * // destination address, you may fill out other attributes but they
 
105
 * // will have no influence.
 
106
 * rtnl_neigh_set_ifindex(neigh, ifindex);
 
107
 * rtnl_neigh_set_dst(neigh, dst_addr);
 
108
 *
 
109
 * // Build the netlink message and send it to the kernel, the operation will
 
110
 * // block until the operation has been completed. Alternatively the required
 
111
 * // netlink message can be built using rtnl_neigh_build_delete_request()
 
112
 * // to be sent out using nl_send_auto_complete().
 
113
 * rtnl_neigh_delete(sk, neigh, 0);
 
114
 *
 
115
 * // Free the memory
 
116
 * rtnl_neigh_put(neigh);
 
117
 * @endcode
 
118
 *
 
119
 * @par 4) Changing neighbour attributes
 
120
 * @code
 
121
 * // Allocate an empty neighbour object to be filled out with the attributes
 
122
 * // matching the neighbour to be changed and the new parameters. Alternatively
 
123
 * // a fully equipped modified neighbour object out of a cache can be used.
 
124
 * struct rtnl_neigh *neigh = rtnl_neigh_alloc();
 
125
 *
 
126
 * // Identify the neighbour to be changed by its interface index and
 
127
 * // destination address
 
128
 * rtnl_neigh_set_ifindex(neigh, ifindex);
 
129
 * rtnl_neigh_set_dst(neigh, dst_addr);
 
130
 *
 
131
 * // The link layer address may be modified, if so it is wise to change
 
132
 * // its state to "permanent" in order to avoid having it overwritten.
 
133
 * rtnl_neigh_set_lladdr(neigh, lladdr);
 
134
 *
 
135
 * // Secondly the state can be modified allowing normal neighbours to be
 
136
 * // converted into permanent entries or to manually confirm a neighbour.
 
137
 * rtnl_neigh_set_state(neigh, state);
 
138
 *
 
139
 * // Build the netlink message and send it to the kernel, the operation will
 
140
 * // block until the operation has been completed. Alternatively the required
 
141
 * // netlink message can be built using rtnl_neigh_build_change_request()
 
142
 * // to be sent out using nl_send_auto_complete().
 
143
 * rtnl_neigh_add(sk, neigh, NLM_F_REPLACE);
 
144
 *
 
145
 * // Free the memory
 
146
 * rtnl_neigh_put(neigh);
 
147
 * @endcode
 
148
 * @{
 
149
 */
 
150
 
 
151
#include <netlink-local.h>
 
152
#include <netlink/netlink.h>
 
153
#include <netlink/utils.h>
 
154
#include <netlink/route/rtnl.h>
 
155
#include <netlink/route/neighbour.h>
 
156
#include <netlink/route/link.h>
 
157
 
 
158
/** @cond SKIP */
 
159
#define NEIGH_ATTR_FLAGS        0x01
 
160
#define NEIGH_ATTR_STATE        0x02
 
161
#define NEIGH_ATTR_LLADDR       0x04
 
162
#define NEIGH_ATTR_DST          0x08
 
163
#define NEIGH_ATTR_CACHEINFO    0x10
 
164
#define NEIGH_ATTR_IFINDEX      0x20
 
165
#define NEIGH_ATTR_FAMILY       0x40
 
166
#define NEIGH_ATTR_TYPE         0x80
 
167
#define NEIGH_ATTR_PROBES       0x100
 
168
 
 
169
static struct nl_cache_ops rtnl_neigh_ops;
 
170
static struct nl_object_ops neigh_obj_ops;
 
171
/** @endcond */
 
172
 
 
173
static void neigh_free_data(struct nl_object *c)
 
174
{
 
175
        struct rtnl_neigh *neigh = nl_object_priv(c);
 
176
 
 
177
        if (!neigh)
 
178
                return;
 
179
 
 
180
        nl_addr_put(neigh->n_lladdr);
 
181
        nl_addr_put(neigh->n_dst);
 
182
}
 
183
 
 
184
static int neigh_clone(struct nl_object *_dst, struct nl_object *_src)
 
185
{
 
186
        struct rtnl_neigh *dst = nl_object_priv(_dst);
 
187
        struct rtnl_neigh *src = nl_object_priv(_src);
 
188
 
 
189
        if (src->n_lladdr)
 
190
                if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr)))
 
191
                        return -NLE_NOMEM;
 
192
 
 
193
        if (src->n_dst)
 
194
                if (!(dst->n_dst = nl_addr_clone(src->n_dst)))
 
195
                        return -NLE_NOMEM;
 
196
 
 
197
        return 0;
 
198
}
 
199
 
 
200
static int neigh_compare(struct nl_object *_a, struct nl_object *_b,
 
201
                        uint32_t attrs, int flags)
 
202
{
 
203
        struct rtnl_neigh *a = (struct rtnl_neigh *) _a;
 
204
        struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
 
205
        int diff = 0;
 
206
 
 
207
#define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
 
208
 
 
209
        diff |= NEIGH_DIFF(IFINDEX,     a->n_ifindex != b->n_ifindex);
 
210
        diff |= NEIGH_DIFF(FAMILY,      a->n_family != b->n_family);
 
211
        diff |= NEIGH_DIFF(TYPE,        a->n_type != b->n_type);
 
212
        diff |= NEIGH_DIFF(LLADDR,      nl_addr_cmp(a->n_lladdr, b->n_lladdr));
 
213
        diff |= NEIGH_DIFF(DST,         nl_addr_cmp(a->n_dst, b->n_dst));
 
214
 
 
215
        if (flags & LOOSE_COMPARISON) {
 
216
                diff |= NEIGH_DIFF(STATE,
 
217
                                  (a->n_state ^ b->n_state) & b->n_state_mask);
 
218
                diff |= NEIGH_DIFF(FLAGS,
 
219
                                  (a->n_flags ^ b->n_flags) & b->n_flag_mask);
 
220
        } else {
 
221
                diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
 
222
                diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
 
223
        }
 
224
 
 
225
#undef NEIGH_DIFF
 
226
 
 
227
        return diff;
 
228
}
 
229
 
 
230
static const struct trans_tbl neigh_attrs[] = {
 
231
        __ADD(NEIGH_ATTR_FLAGS, flags)
 
232
        __ADD(NEIGH_ATTR_STATE, state)
 
233
        __ADD(NEIGH_ATTR_LLADDR, lladdr)
 
234
        __ADD(NEIGH_ATTR_DST, dst)
 
235
        __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo)
 
236
        __ADD(NEIGH_ATTR_IFINDEX, ifindex)
 
237
        __ADD(NEIGH_ATTR_FAMILY, family)
 
238
        __ADD(NEIGH_ATTR_TYPE, type)
 
239
        __ADD(NEIGH_ATTR_PROBES, probes)
 
240
};
 
241
 
 
242
static char *neigh_attrs2str(int attrs, char *buf, size_t len)
 
243
{
 
244
        return __flags2str(attrs, buf, len, neigh_attrs,
 
245
                           ARRAY_SIZE(neigh_attrs));
 
246
}
 
247
 
 
248
static struct nla_policy neigh_policy[NDA_MAX+1] = {
 
249
        [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) },
 
250
        [NDA_PROBES]    = { .type = NLA_U32 },
 
251
};
 
252
 
 
253
static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
 
254
                            struct nlmsghdr *n, struct nl_parser_param *pp)
 
255
{
 
256
        struct rtnl_neigh *neigh;
 
257
        struct nlattr *tb[NDA_MAX + 1];
 
258
        struct ndmsg *nm;
 
259
        int err;
 
260
 
 
261
        neigh = rtnl_neigh_alloc();
 
262
        if (!neigh) {
 
263
                err = -NLE_NOMEM;
 
264
                goto errout;
 
265
        }
 
266
 
 
267
        neigh->ce_msgtype = n->nlmsg_type;
 
268
        nm = nlmsg_data(n);
 
269
 
 
270
        err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy);
 
271
        if (err < 0)
 
272
                goto errout;
 
273
 
 
274
        neigh->n_family  = nm->ndm_family;
 
275
        neigh->n_ifindex = nm->ndm_ifindex;
 
276
        neigh->n_state   = nm->ndm_state;
 
277
        neigh->n_flags   = nm->ndm_flags;
 
278
        neigh->n_type    = nm->ndm_type;
 
279
 
 
280
        neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
 
281
                           NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS |
 
282
                           NEIGH_ATTR_TYPE);
 
283
 
 
284
        if (tb[NDA_LLADDR]) {
 
285
                neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC);
 
286
                if (!neigh->n_lladdr) {
 
287
                        err = -NLE_NOMEM;
 
288
                        goto errout;
 
289
                }
 
290
                nl_addr_set_family(neigh->n_lladdr,
 
291
                                   nl_addr_guess_family(neigh->n_lladdr));
 
292
                neigh->ce_mask |= NEIGH_ATTR_LLADDR;
 
293
        }
 
294
 
 
295
        if (tb[NDA_DST]) {
 
296
                neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family);
 
297
                if (!neigh->n_dst) {
 
298
                        err = -NLE_NOMEM;
 
299
                        goto errout;
 
300
                }
 
301
                neigh->ce_mask |= NEIGH_ATTR_DST;
 
302
        }
 
303
 
 
304
        if (tb[NDA_CACHEINFO]) {
 
305
                struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]);
 
306
 
 
307
                neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed;
 
308
                neigh->n_cacheinfo.nci_used = ci->ndm_used;
 
309
                neigh->n_cacheinfo.nci_updated = ci->ndm_updated;
 
310
                neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt;
 
311
                
 
312
                neigh->ce_mask |= NEIGH_ATTR_CACHEINFO;
 
313
        }
 
314
 
 
315
        if (tb[NDA_PROBES]) {
 
316
                neigh->n_probes = nla_get_u32(tb[NDA_PROBES]);
 
317
                neigh->ce_mask |= NEIGH_ATTR_PROBES;
 
318
        }
 
319
 
 
320
        err = pp->pp_cb((struct nl_object *) neigh, pp);
 
321
errout:
 
322
        rtnl_neigh_put(neigh);
 
323
        return err;
 
324
}
 
325
 
 
326
static int neigh_request_update(struct nl_cache *c, struct nl_sock *h)
 
327
{
 
328
        return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP);
 
329
}
 
330
 
 
331
 
 
332
static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p)
 
333
{
 
334
        char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5];
 
335
        struct rtnl_neigh *n = (struct rtnl_neigh *) a;
 
336
        struct nl_cache *link_cache;
 
337
        char state[128], flags[64];
 
338
 
 
339
        link_cache = nl_cache_mngt_require("route/link");
 
340
 
 
341
        nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst)));
 
342
 
 
343
        if (link_cache)
 
344
                nl_dump(p, "dev %s ",
 
345
                        rtnl_link_i2name(link_cache, n->n_ifindex,
 
346
                                         state, sizeof(state)));
 
347
        else
 
348
                nl_dump(p, "dev %d ", n->n_ifindex);
 
349
 
 
350
        if (n->ce_mask & NEIGH_ATTR_LLADDR)
 
351
                nl_dump(p, "lladdr %s ",
 
352
                        nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr)));
 
353
 
 
354
        rtnl_neigh_state2str(n->n_state, state, sizeof(state));
 
355
        rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags));
 
356
 
 
357
        if (state[0])
 
358
                nl_dump(p, "<%s", state);
 
359
        if (flags[0])
 
360
                nl_dump(p, "%s%s", state[0] ? "," : "<", flags);
 
361
        if (state[0] || flags[0])
 
362
                nl_dump(p, ">");
 
363
        nl_dump(p, "\n");
 
364
}
 
365
 
 
366
static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p)
 
367
{
 
368
        char rtn_type[32];
 
369
        struct rtnl_neigh *n = (struct rtnl_neigh *) a;
 
370
        int hz = nl_get_user_hz();
 
371
 
 
372
        neigh_dump_line(a, p);
 
373
 
 
374
        nl_dump_line(p, "    refcnt %u type %s confirmed %u used "
 
375
                                "%u updated %u\n",
 
376
                n->n_cacheinfo.nci_refcnt,
 
377
                nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)),
 
378
                n->n_cacheinfo.nci_confirmed/hz,
 
379
                n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz);
 
380
}
 
381
 
 
382
static void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p)
 
383
{
 
384
        neigh_dump_details(a, p);
 
385
}
 
386
 
 
387
/**
 
388
 * @name Neighbour Object Allocation/Freeage
 
389
 * @{
 
390
 */
 
391
 
 
392
struct rtnl_neigh *rtnl_neigh_alloc(void)
 
393
{
 
394
        return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops);
 
395
}
 
396
 
 
397
void rtnl_neigh_put(struct rtnl_neigh *neigh)
 
398
{
 
399
        nl_object_put((struct nl_object *) neigh);
 
400
}
 
401
 
 
402
/** @} */
 
403
 
 
404
/**
 
405
 * @name Neighbour Cache Managament
 
406
 * @{
 
407
 */
 
408
 
 
409
/**
 
410
 * Build a neighbour cache including all neighbours currently configured in the kernel.
 
411
 * @arg sk              Netlink socket.
 
412
 * @arg result          Pointer to store resulting cache.
 
413
 *
 
414
 * Allocates a new neighbour cache, initializes it properly and updates it
 
415
 * to include all neighbours currently configured in the kernel.
 
416
 *
 
417
 * @return 0 on success or a negative error code.
 
418
 */
 
419
int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
 
420
{
 
421
        return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result);
 
422
}
 
423
 
 
424
/**
 
425
 * Look up a neighbour by interface index and destination address
 
426
 * @arg cache           neighbour cache
 
427
 * @arg ifindex         interface index the neighbour is on
 
428
 * @arg dst             destination address of the neighbour
 
429
 * @return neighbour handle or NULL if no match was found.
 
430
 */
 
431
struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex,
 
432
                                   struct nl_addr *dst)
 
433
{
 
434
        struct rtnl_neigh *neigh;
 
435
 
 
436
        nl_list_for_each_entry(neigh, &cache->c_items, ce_list) {
 
437
                if (neigh->n_ifindex == ifindex &&
 
438
                    !nl_addr_cmp(neigh->n_dst, dst)) {
 
439
                        nl_object_get((struct nl_object *) neigh);
 
440
                        return neigh;
 
441
                }
 
442
        }
 
443
 
 
444
        return NULL;
 
445
}
 
446
 
 
447
/** @} */
 
448
 
 
449
/**
 
450
 * @name Neighbour Addition
 
451
 * @{
 
452
 */
 
453
 
 
454
static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags,
 
455
                           struct nl_msg **result)
 
456
{
 
457
        struct nl_msg *msg;
 
458
        struct ndmsg nhdr = {
 
459
                .ndm_ifindex = tmpl->n_ifindex,
 
460
                .ndm_state = NUD_PERMANENT,
 
461
        };
 
462
 
 
463
        if (!(tmpl->ce_mask & NEIGH_ATTR_DST))
 
464
                return -NLE_MISSING_ATTR;
 
465
 
 
466
        nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst);
 
467
 
 
468
        if (tmpl->ce_mask & NEIGH_ATTR_STATE)
 
469
                nhdr.ndm_state = tmpl->n_state;
 
470
 
 
471
        msg = nlmsg_alloc_simple(cmd, flags);
 
472
        if (!msg)
 
473
                return -NLE_NOMEM;
 
474
 
 
475
        if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
 
476
                goto nla_put_failure;
 
477
 
 
478
        NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst);
 
479
 
 
480
        if (tmpl->ce_mask & NEIGH_ATTR_LLADDR)
 
481
                NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr);
 
482
 
 
483
        *result = msg;
 
484
        return 0;
 
485
 
 
486
nla_put_failure:
 
487
        nlmsg_free(msg);
 
488
        return -NLE_MSGSIZE;
 
489
}
 
490
 
 
491
/**
 
492
 * Build netlink request message to add a new neighbour
 
493
 * @arg tmpl            template with data of new neighbour
 
494
 * @arg flags           additional netlink message flags
 
495
 * @arg result          Pointer to store resulting message.
 
496
 *
 
497
 * Builds a new netlink message requesting a addition of a new
 
498
 * neighbour. The netlink message header isn't fully equipped with
 
499
 * all relevant fields and must thus be sent out via nl_send_auto_complete()
 
500
 * or supplemented as needed. \a tmpl must contain the attributes of the new
 
501
 * neighbour set via \c rtnl_neigh_set_* functions.
 
502
 * 
 
503
 * The following attributes must be set in the template:
 
504
 *  - Interface index (rtnl_neigh_set_ifindex())
 
505
 *  - State (rtnl_neigh_set_state())
 
506
 *  - Destination address (rtnl_neigh_set_dst())
 
507
 *  - Link layer address (rtnl_neigh_set_lladdr())
 
508
 *
 
509
 * @return 0 on success or a negative error code.
 
510
 */
 
511
int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags,
 
512
                                 struct nl_msg **result)
 
513
{
 
514
        return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result);
 
515
}
 
516
 
 
517
/**
 
518
 * Add a new neighbour
 
519
 * @arg sk              Netlink socket.
 
520
 * @arg tmpl            template with requested changes
 
521
 * @arg flags           additional netlink message flags
 
522
 *
 
523
 * Builds a netlink message by calling rtnl_neigh_build_add_request(),
 
524
 * sends the request to the kernel and waits for the next ACK to be
 
525
 * received and thus blocks until the request has been fullfilled.
 
526
 *
 
527
 * The following attributes must be set in the template:
 
528
 *  - Interface index (rtnl_neigh_set_ifindex())
 
529
 *  - State (rtnl_neigh_set_state())
 
530
 *  - Destination address (rtnl_neigh_set_dst())
 
531
 *  - Link layer address (rtnl_neigh_set_lladdr())
 
532
 *
 
533
 * @return 0 on sucess or a negative error if an error occured.
 
534
 */
 
535
int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags)
 
536
{
 
537
        int err;
 
538
        struct nl_msg *msg;
 
539
        
 
540
        if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0)
 
541
                return err;
 
542
 
 
543
        err = nl_send_auto_complete(sk, msg);
 
544
        nlmsg_free(msg);
 
545
        if (err < 0)
 
546
                return err;
 
547
 
 
548
        return wait_for_ack(sk);
 
549
}
 
550
 
 
551
/** @} */
 
552
 
 
553
/**
 
554
 * @name Neighbour Deletion
 
555
 * @{
 
556
 */
 
557
 
 
558
/**
 
559
 * Build a netlink request message to delete a neighbour
 
560
 * @arg neigh           neighbour to delete
 
561
 * @arg flags           additional netlink message flags
 
562
 * @arg result          Pointer to store resulting message.
 
563
 *
 
564
 * Builds a new netlink message requesting a deletion of a neighbour.
 
565
 * The netlink message header isn't fully equipped with all relevant
 
566
 * fields and must thus be sent out via nl_send_auto_complete()
 
567
 * or supplemented as needed. \a neigh must point to an existing
 
568
 * neighbour.
 
569
 *
 
570
 * @return 0 on success or a negative error code.
 
571
 */
 
572
int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags,
 
573
                                    struct nl_msg **result)
 
574
{
 
575
        return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result);
 
576
}
 
577
 
 
578
/**
 
579
 * Delete a neighbour
 
580
 * @arg sk              Netlink socket.
 
581
 * @arg neigh           neighbour to delete
 
582
 * @arg flags           additional netlink message flags
 
583
 *
 
584
 * Builds a netlink message by calling rtnl_neigh_build_delete_request(),
 
585
 * sends the request to the kernel and waits for the next ACK to be
 
586
 * received and thus blocks until the request has been fullfilled.
 
587
 *
 
588
 * @return 0 on sucess or a negative error if an error occured.
 
589
 */
 
590
int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh,
 
591
                      int flags)
 
592
{
 
593
        struct nl_msg *msg;
 
594
        int err;
 
595
        
 
596
        if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0)
 
597
                return err;
 
598
 
 
599
        err = nl_send_auto_complete(sk, msg);
 
600
        nlmsg_free(msg);
 
601
        if (err < 0)
 
602
                return err;
 
603
 
 
604
        return wait_for_ack(sk);
 
605
}
 
606
 
 
607
/** @} */
 
608
 
 
609
/**
 
610
 * @name Neighbour States Translations
 
611
 * @{
 
612
 */
 
613
 
 
614
static const struct trans_tbl neigh_states[] = {
 
615
        __ADD(NUD_INCOMPLETE, incomplete)
 
616
        __ADD(NUD_REACHABLE, reachable)
 
617
        __ADD(NUD_STALE, stale)
 
618
        __ADD(NUD_DELAY, delay)
 
619
        __ADD(NUD_PROBE, probe)
 
620
        __ADD(NUD_FAILED, failed)
 
621
        __ADD(NUD_NOARP, norarp)
 
622
        __ADD(NUD_PERMANENT, permanent)
 
623
};
 
624
 
 
625
char * rtnl_neigh_state2str(int state, char *buf, size_t len)
 
626
{
 
627
        return __flags2str(state, buf, len, neigh_states,
 
628
            ARRAY_SIZE(neigh_states));
 
629
}
 
630
 
 
631
int rtnl_neigh_str2state(const char *name)
 
632
{
 
633
        return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states));
 
634
}
 
635
 
 
636
/** @} */
 
637
 
 
638
/**
 
639
 * @name Neighbour Flags Translations
 
640
 * @{
 
641
 */
 
642
 
 
643
static const struct trans_tbl neigh_flags[] = {
 
644
        __ADD(NTF_USE, use)
 
645
        __ADD(NTF_PROXY, proxy)
 
646
        __ADD(NTF_ROUTER, router)
 
647
};
 
648
 
 
649
char * rtnl_neigh_flags2str(int flags, char *buf, size_t len)
 
650
{
 
651
        return __flags2str(flags, buf, len, neigh_flags,
 
652
            ARRAY_SIZE(neigh_flags));
 
653
}
 
654
 
 
655
int rtnl_neigh_str2flag(const char *name)
 
656
{
 
657
        return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags));
 
658
}
 
659
 
 
660
/** @} */
 
661
 
 
662
/**
 
663
 * @name Attributes
 
664
 * @{
 
665
 */
 
666
 
 
667
void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state)
 
668
{
 
669
        neigh->n_state_mask |= state;
 
670
        neigh->n_state |= state;
 
671
        neigh->ce_mask |= NEIGH_ATTR_STATE;
 
672
}
 
673
 
 
674
int rtnl_neigh_get_state(struct rtnl_neigh *neigh)
 
675
{
 
676
        if (neigh->ce_mask & NEIGH_ATTR_STATE)
 
677
                return neigh->n_state;
 
678
        else
 
679
                return -1;
 
680
}
 
681
 
 
682
void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state)
 
683
{
 
684
        neigh->n_state_mask |= state;
 
685
        neigh->n_state &= ~state;
 
686
        neigh->ce_mask |= NEIGH_ATTR_STATE;
 
687
}
 
688
 
 
689
void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags)
 
690
{
 
691
        neigh->n_flag_mask |= flags;
 
692
        neigh->n_flags |= flags;
 
693
        neigh->ce_mask |= NEIGH_ATTR_FLAGS;
 
694
}
 
695
 
 
696
unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh)
 
697
{
 
698
        return neigh->n_flags;
 
699
}
 
700
 
 
701
void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags)
 
702
{
 
703
        neigh->n_flag_mask |= flags;
 
704
        neigh->n_flags &= ~flags;
 
705
        neigh->ce_mask |= NEIGH_ATTR_FLAGS;
 
706
}
 
707
 
 
708
void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex)
 
709
{
 
710
        neigh->n_ifindex = ifindex;
 
711
        neigh->ce_mask |= NEIGH_ATTR_IFINDEX;
 
712
}
 
713
 
 
714
int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh)
 
715
{
 
716
        return neigh->n_ifindex;
 
717
}
 
718
 
 
719
static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos,
 
720
                                struct nl_addr *new, int flag, int nocheck)
 
721
{
 
722
        if (!nocheck) {
 
723
                if (neigh->ce_mask & NEIGH_ATTR_FAMILY) {
 
724
                        if (new->a_family != neigh->n_family)
 
725
                                return -NLE_AF_MISMATCH;
 
726
                } else {
 
727
                        neigh->n_family = new->a_family;
 
728
                        neigh->ce_mask |= NEIGH_ATTR_FAMILY;
 
729
                }
 
730
        }
 
731
 
 
732
        if (*pos)
 
733
                nl_addr_put(*pos);
 
734
 
 
735
        nl_addr_get(new);
 
736
        *pos = new;
 
737
 
 
738
        neigh->ce_mask |= flag;
 
739
 
 
740
        return 0;
 
741
}
 
742
 
 
743
void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr)
 
744
{
 
745
        __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1);
 
746
}
 
747
 
 
748
struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh)
 
749
{
 
750
        if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
 
751
                return neigh->n_lladdr;
 
752
        else
 
753
                return NULL;
 
754
}
 
755
 
 
756
int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr)
 
757
{
 
758
        return __assign_addr(neigh, &neigh->n_dst, addr,
 
759
                             NEIGH_ATTR_DST, 0);
 
760
}
 
761
 
 
762
struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh)
 
763
{
 
764
        if (neigh->ce_mask & NEIGH_ATTR_DST)
 
765
                return neigh->n_dst;
 
766
        else
 
767
                return NULL;
 
768
}
 
769
 
 
770
void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family)
 
771
{
 
772
        neigh->n_family = family;
 
773
        neigh->ce_mask |= NEIGH_ATTR_FAMILY;
 
774
}
 
775
 
 
776
int rtnl_neigh_get_family(struct rtnl_neigh *neigh)
 
777
{
 
778
        return neigh->n_family;
 
779
}
 
780
 
 
781
void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type)
 
782
{
 
783
        neigh->n_type = type;
 
784
        neigh->ce_mask = NEIGH_ATTR_TYPE;
 
785
}
 
786
 
 
787
int rtnl_neigh_get_type(struct rtnl_neigh *neigh)
 
788
{
 
789
        if (neigh->ce_mask & NEIGH_ATTR_TYPE)
 
790
                return neigh->n_type;
 
791
        else
 
792
                return -1;
 
793
}
 
794
 
 
795
/** @} */
 
796
 
 
797
static struct nl_object_ops neigh_obj_ops = {
 
798
        .oo_name                = "route/neigh",
 
799
        .oo_size                = sizeof(struct rtnl_neigh),
 
800
        .oo_free_data           = neigh_free_data,
 
801
        .oo_clone               = neigh_clone,
 
802
        .oo_dump = {
 
803
            [NL_DUMP_LINE]      = neigh_dump_line,
 
804
            [NL_DUMP_DETAILS]   = neigh_dump_details,
 
805
            [NL_DUMP_STATS]     = neigh_dump_stats,
 
806
        },
 
807
        .oo_compare             = neigh_compare,
 
808
        .oo_attrs2str           = neigh_attrs2str,
 
809
        .oo_id_attrs            = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
 
810
};
 
811
 
 
812
static struct nl_af_group neigh_groups[] = {
 
813
        { AF_UNSPEC, RTNLGRP_NEIGH },
 
814
        { END_OF_GROUP_LIST },
 
815
};
 
816
 
 
817
static struct nl_cache_ops rtnl_neigh_ops = {
 
818
        .co_name                = "route/neigh",
 
819
        .co_hdrsize             = sizeof(struct ndmsg),
 
820
        .co_msgtypes            = {
 
821
                                        { RTM_NEWNEIGH, NL_ACT_NEW, "new" },
 
822
                                        { RTM_DELNEIGH, NL_ACT_DEL, "del" },
 
823
                                        { RTM_GETNEIGH, NL_ACT_GET, "get" },
 
824
                                        END_OF_MSGTYPES_LIST,
 
825
                                  },
 
826
        .co_protocol            = NETLINK_ROUTE,
 
827
        .co_groups              = neigh_groups,
 
828
        .co_request_update      = neigh_request_update,
 
829
        .co_msg_parser          = neigh_msg_parser,
 
830
        .co_obj_ops             = &neigh_obj_ops,
 
831
};
 
832
 
 
833
static void __init neigh_init(void)
 
834
{
 
835
        nl_cache_mngt_register(&rtnl_neigh_ops);
 
836
}
 
837
 
 
838
static void __exit neigh_exit(void)
 
839
{
 
840
        nl_cache_mngt_unregister(&rtnl_neigh_ops);
 
841
}
 
842
 
 
843
/** @} */