+ for (c=st->clients; c; c=c->next)
+ st->routes[i++]=c;
+ /* Sort the table in descending order of priority */
+ qsort(st->routes,st->n_clients,sizeof(*st->routes),
+ netlink_compare_client_priority);
+
+ netlink_dump_routes(st,False);
+}
+
+static void netlink_signal_handler(void *sst, int signum)
+{
+ struct netlink *st=sst;
+ Message(M_INFO,"%s: route dump requested by SIGUSR1\n",st->name);
+ netlink_dump_routes(st,True);
+}
+
+static void netlink_inst_output_config(void *sst, struct buffer_if *buf)
+{
+/* struct netlink_client *c=sst; */
+/* struct netlink *st=c->nst; */
+
+ /* For now we don't output anything */
+ BUF_ASSERT_USED(buf);
+}
+
+static bool_t netlink_inst_check_config(void *sst, struct buffer_if *buf)
+{
+/* struct netlink_client *c=sst; */
+/* struct netlink *st=c->nst; */
+
+ BUF_ASSERT_USED(buf);
+ /* We need to eat all of the configuration information from the buffer
+ for backward compatibility. */
+ buf->size=0;
+ return True;
+}
+
+static void netlink_inst_set_mtu(void *sst, uint32_t new_mtu)
+{
+ struct netlink_client *c=sst;
+
+ c->mtu=new_mtu;
+}
+
+static void netlink_inst_reg(void *sst, netlink_deliver_fn *deliver,
+ void *dst, uint32_t max_start_pad,
+ uint32_t max_end_pad)
+{
+ struct netlink_client *c=sst;
+ struct netlink *st=c->nst;
+
+ if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad;
+ if (max_end_pad > st->max_end_pad) st->max_end_pad=max_end_pad;
+ c->deliver=deliver;
+ c->dst=dst;
+}
+
+static struct flagstr netlink_option_table[]={
+ { "soft", OPT_SOFTROUTE },
+ { "allow-route", OPT_ALLOWROUTE },
+ { NULL, 0}
+};
+/* This is the routine that gets called when the closure that's
+ returned by an invocation of a netlink device closure (eg. tun,
+ userv-ipif) is invoked. It's used to create routes and pass in
+ information about them; the closure it returns is used by site
+ code. */
+static closure_t *netlink_inst_create(struct netlink *st,
+ struct cloc loc, dict_t *dict)
+{
+ struct netlink_client *c;
+ string_t name;
+ struct ipset *networks;
+ uint32_t options,priority,mtu;
+ list_t *l;
+
+ name=dict_read_string(dict, "name", True, st->name, loc);
+
+ l=dict_lookup(dict,"routes");
+ if (!l)
+ cfgfatal(loc,st->name,"required parameter \"routes\" not found\n");
+ networks=string_list_to_ipset(l,loc,st->name,"routes");
+ options=string_list_to_word(dict_lookup(dict,"options"),
+ netlink_option_table,st->name);
+
+ priority=dict_read_number(dict,"priority",False,st->name,loc,0);
+ mtu=dict_read_number(dict,"mtu",False,st->name,loc,0);
+
+ if ((options&OPT_SOFTROUTE) && !st->set_routes) {
+ cfgfatal(loc,st->name,"this netlink device does not support "
+ "soft routes.\n");
+ return NULL;
+ }
+
+ if (options&OPT_SOFTROUTE) {
+ /* XXX for now we assume that soft routes require root privilege;
+ this may not always be true. The device driver can tell us. */
+ require_root_privileges=True;
+ require_root_privileges_explanation="netlink: soft routes";
+ if (st->ptp) {
+ cfgfatal(loc,st->name,"point-to-point netlinks do not support "
+ "soft routes.\n");
+ return NULL;