00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 #include <netlink-local.h>
00151 #include <netlink/netlink.h>
00152 #include <netlink/utils.h>
00153 #include <netlink/route/rtnl.h>
00154 #include <netlink/route/neighbour.h>
00155 #include <netlink/route/link.h>
00156
00157
00158 #define NEIGH_ATTR_FLAGS 0x01
00159 #define NEIGH_ATTR_STATE 0x02
00160 #define NEIGH_ATTR_LLADDR 0x04
00161 #define NEIGH_ATTR_DST 0x08
00162 #define NEIGH_ATTR_CACHEINFO 0x10
00163 #define NEIGH_ATTR_IFINDEX 0x20
00164 #define NEIGH_ATTR_FAMILY 0x40
00165 #define NEIGH_ATTR_TYPE 0x80
00166 #define NEIGH_ATTR_PROBES 0x100
00167
00168 static struct nl_cache_ops rtnl_neigh_ops;
00169 static struct nl_object_ops neigh_obj_ops;
00170
00171
00172 static void neigh_free_data(struct nl_object *c)
00173 {
00174 struct rtnl_neigh *neigh = nl_object_priv(c);
00175
00176 if (!neigh)
00177 return;
00178
00179 nl_addr_put(neigh->n_lladdr);
00180 nl_addr_put(neigh->n_dst);
00181 }
00182
00183 static int neigh_clone(struct nl_object *_dst, struct nl_object *_src)
00184 {
00185 struct rtnl_neigh *dst = nl_object_priv(_dst);
00186 struct rtnl_neigh *src = nl_object_priv(_src);
00187
00188 if (src->n_lladdr)
00189 if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr)))
00190 return -NLE_NOMEM;
00191
00192 if (src->n_dst)
00193 if (!(dst->n_dst = nl_addr_clone(src->n_dst)))
00194 return -NLE_NOMEM;
00195
00196 return 0;
00197 }
00198
00199 static int neigh_compare(struct nl_object *_a, struct nl_object *_b,
00200 uint32_t attrs, int flags)
00201 {
00202 struct rtnl_neigh *a = (struct rtnl_neigh *) _a;
00203 struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
00204 int diff = 0;
00205
00206 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
00207
00208 diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex);
00209 diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family);
00210 diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type);
00211 diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr));
00212 diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst));
00213
00214 if (flags & LOOSE_COMPARISON) {
00215 diff |= NEIGH_DIFF(STATE,
00216 (a->n_state ^ b->n_state) & b->n_state_mask);
00217 diff |= NEIGH_DIFF(FLAGS,
00218 (a->n_flags ^ b->n_flags) & b->n_flag_mask);
00219 } else {
00220 diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
00221 diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
00222 }
00223
00224 #undef NEIGH_DIFF
00225
00226 return diff;
00227 }
00228
00229 static struct trans_tbl neigh_attrs[] = {
00230 __ADD(NEIGH_ATTR_FLAGS, flags)
00231 __ADD(NEIGH_ATTR_STATE, state)
00232 __ADD(NEIGH_ATTR_LLADDR, lladdr)
00233 __ADD(NEIGH_ATTR_DST, dst)
00234 __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo)
00235 __ADD(NEIGH_ATTR_IFINDEX, ifindex)
00236 __ADD(NEIGH_ATTR_FAMILY, family)
00237 __ADD(NEIGH_ATTR_TYPE, type)
00238 __ADD(NEIGH_ATTR_PROBES, probes)
00239 };
00240
00241 static char *neigh_attrs2str(int attrs, char *buf, size_t len)
00242 {
00243 return __flags2str(attrs, buf, len, neigh_attrs,
00244 ARRAY_SIZE(neigh_attrs));
00245 }
00246
00247 static struct nla_policy neigh_policy[NDA_MAX+1] = {
00248 [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) },
00249 [NDA_PROBES] = { .type = NLA_U32 },
00250 };
00251
00252 static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
00253 struct nlmsghdr *n, struct nl_parser_param *pp)
00254 {
00255 struct rtnl_neigh *neigh;
00256 struct nlattr *tb[NDA_MAX + 1];
00257 struct ndmsg *nm;
00258 int err;
00259
00260 neigh = rtnl_neigh_alloc();
00261 if (!neigh) {
00262 err = -NLE_NOMEM;
00263 goto errout;
00264 }
00265
00266 neigh->ce_msgtype = n->nlmsg_type;
00267 nm = nlmsg_data(n);
00268
00269 err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy);
00270 if (err < 0)
00271 goto errout;
00272
00273 neigh->n_family = nm->ndm_family;
00274 neigh->n_ifindex = nm->ndm_ifindex;
00275 neigh->n_state = nm->ndm_state;
00276 neigh->n_flags = nm->ndm_flags;
00277 neigh->n_type = nm->ndm_type;
00278
00279 neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
00280 NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS |
00281 NEIGH_ATTR_TYPE);
00282
00283 if (tb[NDA_LLADDR]) {
00284 neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC);
00285 if (!neigh->n_lladdr) {
00286 err = -NLE_NOMEM;
00287 goto errout;
00288 }
00289 nl_addr_set_family(neigh->n_lladdr,
00290 nl_addr_guess_family(neigh->n_lladdr));
00291 neigh->ce_mask |= NEIGH_ATTR_LLADDR;
00292 }
00293
00294 if (tb[NDA_DST]) {
00295 neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family);
00296 if (!neigh->n_dst) {
00297 err = -NLE_NOMEM;
00298 goto errout;
00299 }
00300 neigh->ce_mask |= NEIGH_ATTR_DST;
00301 }
00302
00303 if (tb[NDA_CACHEINFO]) {
00304 struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]);
00305
00306 neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed;
00307 neigh->n_cacheinfo.nci_used = ci->ndm_used;
00308 neigh->n_cacheinfo.nci_updated = ci->ndm_updated;
00309 neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt;
00310
00311 neigh->ce_mask |= NEIGH_ATTR_CACHEINFO;
00312 }
00313
00314 if (tb[NDA_PROBES]) {
00315 neigh->n_probes = nla_get_u32(tb[NDA_PROBES]);
00316 neigh->ce_mask |= NEIGH_ATTR_PROBES;
00317 }
00318
00319 err = pp->pp_cb((struct nl_object *) neigh, pp);
00320 errout:
00321 rtnl_neigh_put(neigh);
00322 return err;
00323 }
00324
00325 static int neigh_request_update(struct nl_cache *c, struct nl_sock *h)
00326 {
00327 return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP);
00328 }
00329
00330
00331 static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p)
00332 {
00333 char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5];
00334 struct rtnl_neigh *n = (struct rtnl_neigh *) a;
00335 struct nl_cache *link_cache;
00336 char state[128], flags[64];
00337
00338 link_cache = nl_cache_mngt_require("route/link");
00339
00340 nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst)));
00341
00342 if (link_cache)
00343 nl_dump(p, "dev %s ",
00344 rtnl_link_i2name(link_cache, n->n_ifindex,
00345 state, sizeof(state)));
00346 else
00347 nl_dump(p, "dev %d ", n->n_ifindex);
00348
00349 if (n->ce_mask & NEIGH_ATTR_LLADDR)
00350 nl_dump(p, "lladdr %s ",
00351 nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr)));
00352
00353 rtnl_neigh_state2str(n->n_state, state, sizeof(state));
00354 rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags));
00355
00356 if (state[0])
00357 nl_dump(p, "<%s", state);
00358 if (flags[0])
00359 nl_dump(p, "%s%s", state[0] ? "," : "<", flags);
00360 if (state[0] || flags[0])
00361 nl_dump(p, ">");
00362 nl_dump(p, "\n");
00363 }
00364
00365 static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p)
00366 {
00367 char rtn_type[32];
00368 struct rtnl_neigh *n = (struct rtnl_neigh *) a;
00369 int hz = nl_get_hz();
00370
00371 neigh_dump_line(a, p);
00372
00373 nl_dump_line(p, " refcnt %u type %s confirmed %u used "
00374 "%u updated %u\n",
00375 n->n_cacheinfo.nci_refcnt,
00376 nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)),
00377 n->n_cacheinfo.nci_confirmed/hz,
00378 n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz);
00379 }
00380
00381 static void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p)
00382 {
00383 neigh_dump_details(a, p);
00384 }
00385
00386 static void neigh_dump_env(struct nl_object *obj, struct nl_dump_params *p)
00387 {
00388 struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj;
00389 char buf[128];
00390
00391 nl_dump_line(p, "NEIGH_FAMILY=%s\n",
00392 nl_af2str(neigh->n_family, buf, sizeof(buf)));
00393
00394 if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
00395 nl_dump_line(p, "NEIGHT_LLADDR=%s\n",
00396 nl_addr2str(neigh->n_lladdr, buf, sizeof(buf)));
00397
00398 if (neigh->ce_mask & NEIGH_ATTR_DST)
00399 nl_dump_line(p, "NEIGH_DST=%s\n",
00400 nl_addr2str(neigh->n_dst, buf, sizeof(buf)));
00401
00402 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) {
00403 struct nl_cache *link_cache;
00404
00405 nl_dump_line(p, "NEIGH_IFINDEX=%u\n", neigh->n_ifindex);
00406
00407 link_cache = nl_cache_mngt_require("route/link");
00408 if (link_cache)
00409 nl_dump_line(p, "NEIGH_IFNAME=%s\n",
00410 rtnl_link_i2name(link_cache,
00411 neigh->n_ifindex,
00412 buf, sizeof(buf)));
00413 }
00414
00415 if (neigh->ce_mask & NEIGH_ATTR_PROBES)
00416 nl_dump_line(p, "NEIGH_PROBES=%u\n", neigh->n_probes);
00417
00418 if (neigh->ce_mask & NEIGH_ATTR_TYPE)
00419 nl_dump_line(p, "NEIGH_TYPE=%s\n",
00420 nl_rtntype2str(neigh->n_type, buf, sizeof(buf)));
00421
00422 rtnl_neigh_flags2str(neigh->n_flags, buf, sizeof(buf));
00423 if (buf[0])
00424 nl_dump_line(p, "NEIGH_FLAGS=%s\n", buf);
00425
00426 rtnl_neigh_state2str(neigh->n_state, buf, sizeof(buf));
00427 if (buf[0])
00428 nl_dump_line(p, "NEIGH_STATE=%s\n", buf);
00429 }
00430
00431
00432
00433
00434
00435
00436 struct rtnl_neigh *rtnl_neigh_alloc(void)
00437 {
00438 return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops);
00439 }
00440
00441 void rtnl_neigh_put(struct rtnl_neigh *neigh)
00442 {
00443 nl_object_put((struct nl_object *) neigh);
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result)
00464 {
00465 return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result);
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475 struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex,
00476 struct nl_addr *dst)
00477 {
00478 struct rtnl_neigh *neigh;
00479
00480 nl_list_for_each_entry(neigh, &cache->c_items, ce_list) {
00481 if (neigh->n_ifindex == ifindex &&
00482 !nl_addr_cmp(neigh->n_dst, dst)) {
00483 nl_object_get((struct nl_object *) neigh);
00484 return neigh;
00485 }
00486 }
00487
00488 return NULL;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498 static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags,
00499 struct nl_msg **result)
00500 {
00501 struct nl_msg *msg;
00502 struct ndmsg nhdr = {
00503 .ndm_ifindex = tmpl->n_ifindex,
00504 .ndm_state = NUD_PERMANENT,
00505 };
00506
00507 if (!(tmpl->ce_mask & NEIGH_ATTR_DST))
00508 return -NLE_MISSING_ATTR;
00509
00510 nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst);
00511
00512 if (tmpl->ce_mask & NEIGH_ATTR_STATE)
00513 nhdr.ndm_state = tmpl->n_state;
00514
00515 msg = nlmsg_alloc_simple(cmd, flags);
00516 if (!msg)
00517 return -NLE_NOMEM;
00518
00519 if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
00520 goto nla_put_failure;
00521
00522 NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst);
00523
00524 if (tmpl->ce_mask & NEIGH_ATTR_LLADDR)
00525 NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr);
00526
00527 *result = msg;
00528 return 0;
00529
00530 nla_put_failure:
00531 nlmsg_free(msg);
00532 return -NLE_MSGSIZE;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags,
00556 struct nl_msg **result)
00557 {
00558 return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result);
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags)
00580 {
00581 int err;
00582 struct nl_msg *msg;
00583
00584 if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0)
00585 return err;
00586
00587 err = nl_send_auto_complete(sk, msg);
00588 nlmsg_free(msg);
00589 if (err < 0)
00590 return err;
00591
00592 return wait_for_ack(sk);
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags,
00617 struct nl_msg **result)
00618 {
00619 return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result);
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh,
00635 int flags)
00636 {
00637 struct nl_msg *msg;
00638 int err;
00639
00640 if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0)
00641 return err;
00642
00643 err = nl_send_auto_complete(sk, msg);
00644 nlmsg_free(msg);
00645 if (err < 0)
00646 return err;
00647
00648 return wait_for_ack(sk);
00649 }
00650
00651
00652
00653
00654
00655
00656
00657
00658 static struct trans_tbl neigh_states[] = {
00659 __ADD(NUD_INCOMPLETE, incomplete)
00660 __ADD(NUD_REACHABLE, reachable)
00661 __ADD(NUD_STALE, stale)
00662 __ADD(NUD_DELAY, delay)
00663 __ADD(NUD_PROBE, probe)
00664 __ADD(NUD_FAILED, failed)
00665 __ADD(NUD_NOARP, norarp)
00666 __ADD(NUD_PERMANENT, permanent)
00667 };
00668
00669 char * rtnl_neigh_state2str(int state, char *buf, size_t len)
00670 {
00671 return __flags2str(state, buf, len, neigh_states,
00672 ARRAY_SIZE(neigh_states));
00673 }
00674
00675 int rtnl_neigh_str2state(const char *name)
00676 {
00677 return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states));
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687 static struct trans_tbl neigh_flags[] = {
00688 __ADD(NTF_PROXY, proxy)
00689 __ADD(NTF_ROUTER, router)
00690 };
00691
00692 char * rtnl_neigh_flags2str(int flags, char *buf, size_t len)
00693 {
00694 return __flags2str(flags, buf, len, neigh_flags,
00695 ARRAY_SIZE(neigh_flags));
00696 }
00697
00698 int rtnl_neigh_str2flag(const char *name)
00699 {
00700 return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags));
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710 void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state)
00711 {
00712 neigh->n_state_mask |= state;
00713 neigh->n_state |= state;
00714 neigh->ce_mask |= NEIGH_ATTR_STATE;
00715 }
00716
00717 int rtnl_neigh_get_state(struct rtnl_neigh *neigh)
00718 {
00719 if (neigh->ce_mask & NEIGH_ATTR_STATE)
00720 return neigh->n_state;
00721 else
00722 return -1;
00723 }
00724
00725 void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state)
00726 {
00727 neigh->n_state_mask |= state;
00728 neigh->n_state &= ~state;
00729 neigh->ce_mask |= NEIGH_ATTR_STATE;
00730 }
00731
00732 void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags)
00733 {
00734 neigh->n_flag_mask |= flags;
00735 neigh->n_flags |= flags;
00736 neigh->ce_mask |= NEIGH_ATTR_FLAGS;
00737 }
00738
00739 unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh)
00740 {
00741 return neigh->n_flags;
00742 }
00743
00744 void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags)
00745 {
00746 neigh->n_flag_mask |= flags;
00747 neigh->n_flags &= ~flags;
00748 neigh->ce_mask |= NEIGH_ATTR_FLAGS;
00749 }
00750
00751 void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex)
00752 {
00753 neigh->n_ifindex = ifindex;
00754 neigh->ce_mask |= NEIGH_ATTR_IFINDEX;
00755 }
00756
00757 int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh)
00758 {
00759 return neigh->n_ifindex;
00760 }
00761
00762 static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos,
00763 struct nl_addr *new, int flag, int nocheck)
00764 {
00765 if (!nocheck) {
00766 if (neigh->ce_mask & NEIGH_ATTR_FAMILY) {
00767 if (new->a_family != neigh->n_family)
00768 return -NLE_AF_MISMATCH;
00769 } else {
00770 neigh->n_family = new->a_family;
00771 neigh->ce_mask |= NEIGH_ATTR_FAMILY;
00772 }
00773 }
00774
00775 if (*pos)
00776 nl_addr_put(*pos);
00777
00778 nl_addr_get(new);
00779 *pos = new;
00780
00781 neigh->ce_mask |= flag;
00782
00783 return 0;
00784 }
00785
00786 void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr)
00787 {
00788 __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1);
00789 }
00790
00791 struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh)
00792 {
00793 if (neigh->ce_mask & NEIGH_ATTR_LLADDR)
00794 return neigh->n_lladdr;
00795 else
00796 return NULL;
00797 }
00798
00799 int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr)
00800 {
00801 return __assign_addr(neigh, &neigh->n_dst, addr,
00802 NEIGH_ATTR_DST, 0);
00803 }
00804
00805 struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh)
00806 {
00807 if (neigh->ce_mask & NEIGH_ATTR_DST)
00808 return neigh->n_dst;
00809 else
00810 return NULL;
00811 }
00812
00813 void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family)
00814 {
00815 neigh->n_family = family;
00816 neigh->ce_mask |= NEIGH_ATTR_FAMILY;
00817 }
00818
00819 int rtnl_neigh_get_family(struct rtnl_neigh *neigh)
00820 {
00821 return neigh->n_family;
00822 }
00823
00824 void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type)
00825 {
00826 neigh->n_type = type;
00827 neigh->ce_mask = NEIGH_ATTR_TYPE;
00828 }
00829
00830 int rtnl_neigh_get_type(struct rtnl_neigh *neigh)
00831 {
00832 if (neigh->ce_mask & NEIGH_ATTR_TYPE)
00833 return neigh->n_type;
00834 else
00835 return -1;
00836 }
00837
00838
00839
00840 static struct nl_object_ops neigh_obj_ops = {
00841 .oo_name = "route/neigh",
00842 .oo_size = sizeof(struct rtnl_neigh),
00843 .oo_free_data = neigh_free_data,
00844 .oo_clone = neigh_clone,
00845 .oo_dump = {
00846 [NL_DUMP_LINE] = neigh_dump_line,
00847 [NL_DUMP_DETAILS] = neigh_dump_details,
00848 [NL_DUMP_STATS] = neigh_dump_stats,
00849 [NL_DUMP_ENV] = neigh_dump_env,
00850 },
00851 .oo_compare = neigh_compare,
00852 .oo_attrs2str = neigh_attrs2str,
00853 .oo_id_attrs = (NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY),
00854 };
00855
00856 static struct nl_af_group neigh_groups[] = {
00857 { AF_UNSPEC, RTNLGRP_NEIGH },
00858 { END_OF_GROUP_LIST },
00859 };
00860
00861 static struct nl_cache_ops rtnl_neigh_ops = {
00862 .co_name = "route/neigh",
00863 .co_hdrsize = sizeof(struct ndmsg),
00864 .co_msgtypes = {
00865 { RTM_NEWNEIGH, NL_ACT_NEW, "new" },
00866 { RTM_DELNEIGH, NL_ACT_DEL, "del" },
00867 { RTM_GETNEIGH, NL_ACT_GET, "get" },
00868 END_OF_MSGTYPES_LIST,
00869 },
00870 .co_protocol = NETLINK_ROUTE,
00871 .co_groups = neigh_groups,
00872 .co_request_update = neigh_request_update,
00873 .co_msg_parser = neigh_msg_parser,
00874 .co_obj_ops = &neigh_obj_ops,
00875 };
00876
00877 static void __init neigh_init(void)
00878 {
00879 nl_cache_mngt_register(&rtnl_neigh_ops);
00880 }
00881
00882 static void __exit neigh_exit(void)
00883 {
00884 nl_cache_mngt_unregister(&rtnl_neigh_ops);
00885 }
00886
00887