/** * Allocate link object of type veth * * @return Allocated link object or NULL. */ struct rtnl_link *rtnl_link_veth_alloc(void) { struct rtnl_link *link, *peer; int err; if (!(link = rtnl_link_alloc())) return NULL; if (!(peer = rtnl_link_alloc())) { rtnl_link_put(link); return NULL; } if ((err = rtnl_link_set_type(link, "veth")) < 0) { rtnl_link_put(peer); rtnl_link_put(link); return NULL; } if ((err = rtnl_link_set_type(peer, "veth")) < 0) { rtnl_link_put(peer); rtnl_link_put(link); return NULL; } link->l_info = peer; peer->l_info = link; return link; }
int main(int argc, char *argv[]) { struct rtnl_link *link; struct nl_sock *sk; int err; sk = nl_socket_alloc(); if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) { nl_perror(err, "Unable to connect socket"); return err; } link = rtnl_link_alloc(); rtnl_link_set_name(link, "my_bond"); if ((err = rtnl_link_set_type(link, "bond")) < 0) { nl_perror(err, "Unable to set link info type"); return err; } if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { nl_perror(err, "Unable to add link"); return err; } rtnl_link_put(link); nl_close(sk); return 0; }
/** * Create a new kernel bonding device * @arg sock netlink socket * @arg name name of bonding device or NULL * @arg opts bonding options (currently unused) * * Creates a new bonding device in the kernel. If no name is * provided, the kernel will automatically pick a name of the * form "type%d" (e.g. bond0, vlan1, etc.) * * The \a opts argument is currently unused. In the future, it * may be used to carry additional bonding options to be set * when creating the bonding device. * * @note When letting the kernel assign a name, it will become * difficult to retrieve the interface afterwards because * you have to guess the name the kernel has chosen. It is * therefore not recommended to not provide a device name. * * @see rtnl_link_bond_enslave() * @see rtnl_link_bond_release() * * @return 0 on success or a negative error code */ int rtnl_link_bond_add(struct nl_sock *sock, const char *name, struct rtnl_link *opts) { struct rtnl_link *link; int err; if (!(link = rtnl_link_alloc())) return -NLE_NOMEM; if (!name) { if (opts) name = rtnl_link_get_name(opts); if (!name) return -NLE_MISSING_ATTR; } if ((err = rtnl_link_set_type(link, "bond")) < 0) goto errout; rtnl_link_set_name(link, name); err = rtnl_link_add(sock, link, NLM_F_CREATE); errout: rtnl_link_put(link); return err; }
/** * Allocate link object of type VLAN * * @return Allocated link object or NULL. */ struct rtnl_link *rtnl_link_vlan_alloc(void) { struct rtnl_link *link; int err; if (!(link = rtnl_link_alloc())) return NULL; if ((err = rtnl_link_set_type(link, "vlan")) < 0) { rtnl_link_put(link); return NULL; } return link; }
static int veth_clone(struct rtnl_link *dst, struct rtnl_link *src) { struct rtnl_link *dst_peer , *src_peer = src->l_info; int err; dst_peer = dst->l_info = rtnl_link_alloc(); if (!dst_peer || !src_peer) return -NLE_NOMEM; if ((err = rtnl_link_set_type(dst, "veth")) < 0) { rtnl_link_put(dst_peer); return err; } memcpy(dst_peer, src_peer, sizeof(struct rtnl_link)); return 0; }
int create_bridge(struct nl_sock *sk, struct nl_cache *link_cache, const char *name) { struct rtnl_link *link; int err; link = rtnl_link_alloc(); if ((err = rtnl_link_set_type(link, "bridge")) < 0) { rtnl_link_put(link); return err; } rtnl_link_set_name(link, name); if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0) { return err; } rtnl_link_put(link); return 0; }
static int vlan_clone(struct rtnl_link *dst, struct rtnl_link *src) { struct vlan_info *vdst, *vsrc = src->l_info; int err; dst->l_info = NULL; if ((err = rtnl_link_set_type(dst, "vlan")) < 0) return err; vdst = dst->l_info; vdst->vi_egress_qos = calloc(vsrc->vi_egress_size, sizeof(struct vlan_map)); if (!vdst->vi_egress_qos) return -NLE_NOMEM; memcpy(vdst->vi_egress_qos, vsrc->vi_egress_qos, vsrc->vi_egress_size * sizeof(struct vlan_map)); return 0; }
/** * Add a link to a bond (enslave) * @arg sock netlink socket * @arg master ifindex of bonding master * @arg slave ifindex of slave link to add to bond * * This function is identical to rtnl_link_bond_enslave() except that * it takes interface indices instead of rtnl_link objcets. * * @see rtnl_link_bond_enslave() * * @return 0 on success or a negative error code. */ int rtnl_link_bond_enslave_ifindex(struct nl_sock *sock, int master, int slave) { struct rtnl_link *link; int err; if (!(link = rtnl_link_alloc())) return -NLE_NOMEM; if ((err = rtnl_link_set_type(link, "bond")) < 0) goto errout; rtnl_link_set_ifindex(link, slave); rtnl_link_set_master(link, master); if ((err = rtnl_link_change(sock, link, link, 0)) < 0) goto errout; rtnl_link_put(link); /* * Due to the kernel not signaling whether this opertion is * supported or not, we will retrieve the attribute to see if the * request was successful. If the master assigned remains unchanged * we will return NLE_OPNOTSUPP to allow performing backwards * compatibility of some sort. */ if ((err = rtnl_link_get_kernel(sock, slave, NULL, &link)) < 0) return err; if (rtnl_link_get_master(link) != master) err = -NLE_OPNOTSUPP; errout: rtnl_link_put(link); return err; }
/* * Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and * tagged interface 'if_name'. * * returns -1 on error * returns 1 if the interface already exists * returns 0 otherwise */ int vlan_add(const char *if_name, int vid, const char *vlan_if_name) { int ret = -1; struct nl_sock *handle = NULL; struct nl_cache *cache = NULL; struct rtnl_link *rlink = NULL; int if_idx = 0; wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, " "vlan_if_name=%s)", if_name, vid, vlan_if_name); if ((os_strlen(if_name) + 1) > IFNAMSIZ) { wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", if_name); return -1; } if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) { wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", vlan_if_name); return -1; } handle = nl_socket_alloc(); if (!handle) { wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket"); goto vlan_add_error; } if (nl_connect(handle, NETLINK_ROUTE) < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink"); goto vlan_add_error; } if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) { cache = NULL; wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache"); goto vlan_add_error; } if (!(if_idx = rtnl_link_name2i(cache, if_name))) { /* link does not exist */ wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist", if_name); goto vlan_add_error; } if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) { /* link does exist */ rtnl_link_put(rlink); rlink = NULL; wpa_printf(MSG_ERROR, "VLAN: interface %s already exists", vlan_if_name); ret = 1; goto vlan_add_error; } rlink = rtnl_link_alloc(); if (!rlink) { wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link"); goto vlan_add_error; } if (rtnl_link_set_type(rlink, "vlan") < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to set link type"); goto vlan_add_error; } rtnl_link_set_link(rlink, if_idx); rtnl_link_set_name(rlink, vlan_if_name); if (rtnl_link_vlan_set_id(rlink, vid) < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id"); goto vlan_add_error; } if (rtnl_link_add(handle, rlink, NLM_F_CREATE) < 0) { wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for " "vlan %d on %s (%d)", vlan_if_name, vid, if_name, if_idx); goto vlan_add_error; } ret = 0; vlan_add_error: if (rlink) rtnl_link_put(rlink); if (cache) nl_cache_free(cache); if (handle) nl_socket_free(handle); return ret; }