static int route_table_reset(void) { struct nl_dump dump; struct rtgenmsg *rtmsg; uint64_t reply_stub[NL_DUMP_BUFSIZE / 8]; struct ofpbuf request, reply, buf; route_map_clear(); route_table_valid = true; rt_change_seq++; ofpbuf_init(&request, 0); nl_msg_put_nlmsghdr(&request, sizeof *rtmsg, RTM_GETROUTE, NLM_F_REQUEST); rtmsg = ofpbuf_put_zeros(&request, sizeof *rtmsg); rtmsg->rtgen_family = AF_UNSPEC; nl_dump_start(&dump, NETLINK_ROUTE, &request); ofpbuf_uninit(&request); ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub); while (nl_dump_next(&dump, &reply, &buf)) { struct route_table_msg msg; if (route_table_parse(&reply, &msg)) { route_table_handle_msg(&msg); } } ofpbuf_uninit(&buf); return nl_dump_done(&dump); }
/* Initialize a conntrack netlink dump. */ int nl_ct_dump_start(struct nl_ct_dump_state **statep, const uint16_t *zone) { struct nl_ct_dump_state *state; *statep = state = xzalloc(sizeof *state); ofpbuf_init(&state->buf, NL_DUMP_BUFSIZE); if (zone) { state->filter_zone = true; state->zone = *zone; } nl_msg_put_nfgenmsg(&state->buf, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, NLM_F_REQUEST); nl_dump_start(&state->dump, NETLINK_NETFILTER, &state->buf); ofpbuf_clear(&state->buf); return 0; }
int nl_ct_flush_zone(uint16_t flush_zone) { /* Apparently, there's no netlink interface to flush a specific zone. * This code dumps every connection, checks the zone and eventually * delete the entry. * * This is race-prone, but it is better than using shell scripts. */ struct nl_dump dump; struct ofpbuf buf, reply, delete; ofpbuf_init(&buf, NL_DUMP_BUFSIZE); ofpbuf_init(&delete, NL_DUMP_BUFSIZE); nl_msg_put_nfgenmsg(&buf, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, NLM_F_REQUEST); nl_dump_start(&dump, NETLINK_NETFILTER, &buf); ofpbuf_clear(&buf); for (;;) { struct nlattr *attrs[ARRAY_SIZE(nfnlgrp_conntrack_policy)]; enum nl_ct_event_type event_type; uint8_t nfgen_family; uint16_t zone = 0; if (!nl_dump_next(&dump, &reply, &buf)) { break; } if (!nl_ct_parse_header_policy(&reply, &event_type, &nfgen_family, attrs)) { continue; }; if (attrs[CTA_ZONE]) { zone = ntohs(nl_attr_get_be16(attrs[CTA_ZONE])); } if (zone != flush_zone) { /* The entry is not in the zone we're flushing. */ continue; } nl_msg_put_nfgenmsg(&delete, 0, nfgen_family, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST); nl_msg_put_be16(&delete, CTA_ZONE, htons(zone)); nl_msg_put_unspec(&delete, CTA_TUPLE_ORIG, attrs[CTA_TUPLE_ORIG] + 1, attrs[CTA_TUPLE_ORIG]->nla_len - NLA_HDRLEN); nl_msg_put_unspec(&delete, CTA_ID, attrs[CTA_ID] + 1, attrs[CTA_ID]->nla_len - NLA_HDRLEN); nl_transact(NETLINK_NETFILTER, &delete, NULL); ofpbuf_clear(&delete); } nl_dump_done(&dump); ofpbuf_uninit(&delete); ofpbuf_uninit(&buf); /* Expectations are flushed automatically, because they do not * have a master connection anymore */ return 0; }