1b1d757bcSAlan Somers /* 2b1d757bcSAlan Somers * Copyright (c) 1983, 1993 3b1d757bcSAlan Somers * The Regents of the University of California. All rights reserved. 4b1d757bcSAlan Somers * 5b1d757bcSAlan Somers * Redistribution and use in source and binary forms, with or without 6b1d757bcSAlan Somers * modification, are permitted provided that the following conditions 7b1d757bcSAlan Somers * are met: 8b1d757bcSAlan Somers * 1. Redistributions of source code must retain the above copyright 9b1d757bcSAlan Somers * notice, this list of conditions and the following disclaimer. 10b1d757bcSAlan Somers * 2. Redistributions in binary form must reproduce the above copyright 11b1d757bcSAlan Somers * notice, this list of conditions and the following disclaimer in the 12b1d757bcSAlan Somers * documentation and/or other materials provided with the distribution. 13b1d757bcSAlan Somers * 3. Neither the name of the University nor the names of its contributors 14b1d757bcSAlan Somers * may be used to endorse or promote products derived from this software 15b1d757bcSAlan Somers * without specific prior written permission. 16b1d757bcSAlan Somers * 17b1d757bcSAlan Somers * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18b1d757bcSAlan Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19b1d757bcSAlan Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20b1d757bcSAlan Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21b1d757bcSAlan Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22b1d757bcSAlan Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23b1d757bcSAlan Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24b1d757bcSAlan Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25b1d757bcSAlan Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26b1d757bcSAlan Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27b1d757bcSAlan Somers * SUCH DAMAGE. 28b1d757bcSAlan Somers * 29b1d757bcSAlan Somers * $FreeBSD$ 30b1d757bcSAlan Somers */ 31b1d757bcSAlan Somers #include <sys/param.h> 32b1d757bcSAlan Somers #include <sys/ioctl.h> 33b1d757bcSAlan Somers 34b1d757bcSAlan Somers #include <net/if.h> 35b1d757bcSAlan Somers #include <netinet/ip_carp.h> 3640e04359SKristof Provost #include <netinet/ip_carp_nl.h> 3740e04359SKristof Provost 3840e04359SKristof Provost #include <netlink/netlink.h> 3940e04359SKristof Provost #include <netlink/netlink_generic.h> 4040e04359SKristof Provost #include <netlink/netlink_snl.h> 4140e04359SKristof Provost #include <netlink/netlink_snl_generic.h> 42*13781800SKristof Provost #include <netlink/netlink_snl_route.h> 43b1d757bcSAlan Somers 44b1d757bcSAlan Somers #include <string.h> 45b1d757bcSAlan Somers #include <strings.h> 46b1d757bcSAlan Somers 47b1d757bcSAlan Somers #include "libifconfig.h" 48b1d757bcSAlan Somers #include "libifconfig_internal.h" 49b1d757bcSAlan Somers 5040e04359SKristof Provost #include <stdio.h> 51b1d757bcSAlan Somers 5240e04359SKristof Provost #define _OUT(_field) offsetof(struct ifconfig_carp, _field) 5340e04359SKristof Provost static struct snl_attr_parser ap_carp_get[] = { 5440e04359SKristof Provost { .type = CARP_NL_VHID, .off = _OUT(carpr_vhid), .cb = snl_attr_get_uint32 }, 5540e04359SKristof Provost { .type = CARP_NL_STATE, .off = _OUT(carpr_state), .cb = snl_attr_get_uint32 }, 5640e04359SKristof Provost { .type = CARP_NL_ADVBASE, .off = _OUT(carpr_advbase), .cb = snl_attr_get_int32 }, 5740e04359SKristof Provost { .type = CARP_NL_ADVSKEW, .off = _OUT(carpr_advskew), .cb = snl_attr_get_int32 }, 5840e04359SKristof Provost { .type = CARP_NL_KEY, .off = _OUT(carpr_key), .cb = snl_attr_get_string }, 59*13781800SKristof Provost { .type = CARP_NL_ADDR, .off = _OUT(carpr_addr), .cb = snl_attr_get_in_addr }, 60*13781800SKristof Provost { .type = CARP_NL_ADDR6, .off = _OUT(carpr_addr6), .cb = snl_attr_get_in6_addr }, 6140e04359SKristof Provost }; 6240e04359SKristof Provost #undef _OUT 6340e04359SKristof Provost 6440e04359SKristof Provost SNL_DECLARE_GENL_PARSER(carp_get_parser, ap_carp_get); 6540e04359SKristof Provost 6640e04359SKristof Provost static int 6740e04359SKristof Provost _ifconfig_carp_get(ifconfig_handle_t *h, const char *name, 6840e04359SKristof Provost struct ifconfig_carp *carp, size_t ncarp, uint32_t vhid) 69b1d757bcSAlan Somers { 7040e04359SKristof Provost struct snl_state ss = {}; 7140e04359SKristof Provost struct snl_errmsg_data e = {}; 7240e04359SKristof Provost struct snl_writer nw; 7340e04359SKristof Provost struct nlmsghdr *hdr; 7440e04359SKristof Provost size_t i = 0; 7540e04359SKristof Provost uint32_t seq_id; 7640e04359SKristof Provost unsigned int ifindex; 7740e04359SKristof Provost int family_id; 78b1d757bcSAlan Somers 7940e04359SKristof Provost ifconfig_error_clear(h); 80b1d757bcSAlan Somers 8140e04359SKristof Provost ifindex = if_nametoindex(name); 8240e04359SKristof Provost if (ifindex == 0) { 8340e04359SKristof Provost ifconfig_error(h, NETLINK, ENOENT); 84b1d757bcSAlan Somers return (-1); 85b1d757bcSAlan Somers } 86b1d757bcSAlan Somers 8740e04359SKristof Provost if (! snl_init(&ss, NETLINK_GENERIC)) { 8840e04359SKristof Provost ifconfig_error(h, NETLINK, ENOTSUP); 8940e04359SKristof Provost return (-1); 9040e04359SKristof Provost } 9140e04359SKristof Provost 9240e04359SKristof Provost snl_init_writer(&ss, &nw); 9340e04359SKristof Provost 9440e04359SKristof Provost family_id = snl_get_genl_family(&ss, CARP_NL_FAMILY_NAME); 9540e04359SKristof Provost if (family_id == 0) { 9640e04359SKristof Provost ifconfig_error(h, NETLINK, EPROTONOSUPPORT); 9740e04359SKristof Provost goto out; 9840e04359SKristof Provost } 9940e04359SKristof Provost 10040e04359SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, CARP_NL_CMD_GET); 10140e04359SKristof Provost hdr->nlmsg_flags |= NLM_F_DUMP; 10240e04359SKristof Provost 10340e04359SKristof Provost snl_add_msg_attr_u32(&nw, CARP_NL_IFINDEX, ifindex); 10440e04359SKristof Provost 10540e04359SKristof Provost if (vhid != 0) 10640e04359SKristof Provost snl_add_msg_attr_u32(&nw, CARP_NL_VHID, vhid); 10740e04359SKristof Provost 10840e04359SKristof Provost hdr = snl_finalize_msg(&nw); 10940e04359SKristof Provost if (hdr == NULL) { 11040e04359SKristof Provost ifconfig_error(h, NETLINK, ENOMEM); 11140e04359SKristof Provost goto out; 11240e04359SKristof Provost } 11340e04359SKristof Provost seq_id = hdr->nlmsg_seq; 11440e04359SKristof Provost if (! snl_send_message(&ss, hdr)) { 11540e04359SKristof Provost ifconfig_error(h, NETLINK, EIO); 11640e04359SKristof Provost goto out; 11740e04359SKristof Provost } 11840e04359SKristof Provost 11940e04359SKristof Provost while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) { 12040e04359SKristof Provost if (e.error != 0) { 12140e04359SKristof Provost ifconfig_error(h, NETLINK, e.error); 12240e04359SKristof Provost break; 12340e04359SKristof Provost } 12440e04359SKristof Provost 12540e04359SKristof Provost if (i >= ncarp) { 12640e04359SKristof Provost ifconfig_error(h, NETLINK, E2BIG); 12740e04359SKristof Provost break; 12840e04359SKristof Provost } 12940e04359SKristof Provost 13040e04359SKristof Provost memset(&carp[i], 0, sizeof(carp[0])); 13140e04359SKristof Provost if (! snl_parse_nlmsg(&ss, hdr, &carp_get_parser, &carp[i])) 13240e04359SKristof Provost continue; 13340e04359SKristof Provost 13440e04359SKristof Provost i++; 13540e04359SKristof Provost carp[0].carpr_count = i; 13640e04359SKristof Provost 13740e04359SKristof Provost if (i > ncarp) { 13840e04359SKristof Provost ifconfig_error(h, NETLINK, E2BIG); 13940e04359SKristof Provost break; 14040e04359SKristof Provost } 14140e04359SKristof Provost } 14240e04359SKristof Provost 14340e04359SKristof Provost out: 14440e04359SKristof Provost snl_free(&ss); 14540e04359SKristof Provost 14640e04359SKristof Provost return (h->error.errcode ? -1 : 0); 14740e04359SKristof Provost } 14840e04359SKristof Provost 14940e04359SKristof Provost int 15040e04359SKristof Provost ifconfig_carp_set_info(ifconfig_handle_t *h, const char *name, 15140e04359SKristof Provost const struct ifconfig_carp *carpr) 15240e04359SKristof Provost { 15340e04359SKristof Provost struct snl_state ss = {}; 15440e04359SKristof Provost struct snl_writer nw; 15540e04359SKristof Provost struct nlmsghdr *hdr; 15640e04359SKristof Provost unsigned int ifindex; 15740e04359SKristof Provost int family_id; 15840e04359SKristof Provost uint32_t seq_id; 15940e04359SKristof Provost 16040e04359SKristof Provost ifconfig_error_clear(h); 16140e04359SKristof Provost 16240e04359SKristof Provost ifindex = if_nametoindex(name); 16340e04359SKristof Provost if (ifindex == 0) { 16440e04359SKristof Provost ifconfig_error(h, NETLINK, ENOENT); 16540e04359SKristof Provost return (-1); 16640e04359SKristof Provost } 16740e04359SKristof Provost 16840e04359SKristof Provost if (! snl_init(&ss, NETLINK_GENERIC)) { 16940e04359SKristof Provost ifconfig_error(h, NETLINK, ENOTSUP); 17040e04359SKristof Provost return (-1); 17140e04359SKristof Provost } 17240e04359SKristof Provost 17340e04359SKristof Provost snl_init_writer(&ss, &nw); 17440e04359SKristof Provost 17540e04359SKristof Provost family_id = snl_get_genl_family(&ss, CARP_NL_FAMILY_NAME); 17640e04359SKristof Provost if (family_id == 0) { 17740e04359SKristof Provost ifconfig_error(h, NETLINK, EPROTONOSUPPORT); 17840e04359SKristof Provost return (-1); 17940e04359SKristof Provost } 18040e04359SKristof Provost hdr = snl_create_genl_msg_request(&nw, family_id, CARP_NL_CMD_SET); 18140e04359SKristof Provost 18240e04359SKristof Provost snl_add_msg_attr_u32(&nw, CARP_NL_VHID, carpr->carpr_vhid); 18340e04359SKristof Provost snl_add_msg_attr_u32(&nw, CARP_NL_STATE, carpr->carpr_state); 18440e04359SKristof Provost snl_add_msg_attr_s32(&nw, CARP_NL_ADVBASE, carpr->carpr_advbase); 18540e04359SKristof Provost snl_add_msg_attr_s32(&nw, CARP_NL_ADVSKEW, carpr->carpr_advskew); 18640e04359SKristof Provost snl_add_msg_attr_u32(&nw, CARP_NL_IFINDEX, ifindex); 187*13781800SKristof Provost snl_add_msg_attr(&nw, CARP_NL_ADDR, sizeof(carpr->carpr_addr), 188*13781800SKristof Provost &carpr->carpr_addr); 189*13781800SKristof Provost snl_add_msg_attr(&nw, CARP_NL_ADDR6, sizeof(carpr->carpr_addr6), 190*13781800SKristof Provost &carpr->carpr_addr6); 19140e04359SKristof Provost 19240e04359SKristof Provost hdr = snl_finalize_msg(&nw); 19340e04359SKristof Provost if (hdr == NULL) { 19440e04359SKristof Provost ifconfig_error(h, NETLINK, ENOMEM); 19540e04359SKristof Provost goto out; 19640e04359SKristof Provost } 19740e04359SKristof Provost 19840e04359SKristof Provost seq_id = hdr->nlmsg_seq; 19940e04359SKristof Provost if (! snl_send_message(&ss, hdr)) { 20040e04359SKristof Provost ifconfig_error(h, NETLINK, EIO); 20140e04359SKristof Provost goto out; 20240e04359SKristof Provost } 20340e04359SKristof Provost 20440e04359SKristof Provost struct snl_errmsg_data e = { }; 20540e04359SKristof Provost if (! snl_read_reply_code(&ss, seq_id, &e)) 20640e04359SKristof Provost ifconfig_error(h, NETLINK, e.error); 20740e04359SKristof Provost 20840e04359SKristof Provost out: 20940e04359SKristof Provost snl_free(&ss); 21040e04359SKristof Provost 21140e04359SKristof Provost return (h->error.errcode ? -1 : 0); 21240e04359SKristof Provost } 21340e04359SKristof Provost 21440e04359SKristof Provost int 21540e04359SKristof Provost ifconfig_carp_get_vhid(ifconfig_handle_t *h, const char *name, 21640e04359SKristof Provost struct ifconfig_carp *carp, uint32_t vhid) 21740e04359SKristof Provost { 21840e04359SKristof Provost return (_ifconfig_carp_get(h, name, carp, 1, vhid)); 21940e04359SKristof Provost } 22040e04359SKristof Provost 22140e04359SKristof Provost int 22240e04359SKristof Provost ifconfig_carp_get_info(ifconfig_handle_t *h, const char *name, 22340e04359SKristof Provost struct ifconfig_carp *carp, size_t ncarp) 22440e04359SKristof Provost { 22540e04359SKristof Provost return (_ifconfig_carp_get(h, name, carp, ncarp, 0)); 226b1d757bcSAlan Somers } 227