1 /* NHRP netlink/GRE tunnel configuration code
2 * Copyright (c) 2014-2016 Timo Teräs
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
10 #include <sys/socket.h>
11 #include <linux/netlink.h>
12 #include <linux/rtnetlink.h>
16 #include <linux/ipv6.h>
17 #include <linux/if_tunnel.h>
23 static int __netlink_gre_get_data(struct zbuf *zb, struct zbuf *data, int ifindex)
26 struct ifinfomsg *ifi;
27 struct zbuf payload, rtapayload;
30 debugf(NHRP_DEBUG_KERNEL, "netlink-link-gre: get-info %u", ifindex);
32 n = znl_nlmsg_push(zb, RTM_GETLINK, NLM_F_REQUEST);
33 ifi = znl_push(zb, sizeof(*ifi));
34 *ifi = (struct ifinfomsg) {
37 znl_nlmsg_complete(zb, n);
39 if (zbuf_send(zb, netlink_req_fd) < 0 ||
40 zbuf_recv(zb, netlink_req_fd) < 0)
43 n = znl_nlmsg_pull(zb, &payload);
46 if (n->nlmsg_type != RTM_NEWLINK)
49 ifi = znl_pull(&payload, sizeof(struct ifinfomsg));
53 debugf(NHRP_DEBUG_KERNEL, "netlink-link-gre: ifindex %u, receive msg_type %u, msg_flags %u",
54 ifi->ifi_index, n->nlmsg_type, n->nlmsg_flags);
56 if (ifi->ifi_index != ifindex)
59 while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
60 if (rta->rta_type == IFLA_LINKINFO)
65 while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
66 if (rta->rta_type == IFLA_INFO_DATA)
74 void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key, unsigned int *link_index, struct in_addr *saddr)
76 struct zbuf *zb = zbuf_alloc(8192), data, rtapl;
83 if (__netlink_gre_get_data(zb, &data, ifindex) < 0)
86 while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
87 switch (rta->rta_type) {
89 *link_index = zbuf_get32(&rtapl);
93 *gre_key = zbuf_get32(&rtapl);
96 saddr->s_addr = zbuf_get32(&rtapl);
104 void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index)
107 struct ifinfomsg *ifi;
108 struct rtattr *rta_info, *rta_data, *rta;
109 struct zbuf *zr = zbuf_alloc(8192), data, rtapl;
110 struct zbuf *zb = zbuf_alloc(8192);
113 if (__netlink_gre_get_data(zr, &data, ifindex) < 0)
116 n = znl_nlmsg_push(zb, RTM_NEWLINK, NLM_F_REQUEST);
117 ifi = znl_push(zb, sizeof(*ifi));
118 *ifi = (struct ifinfomsg) {
119 .ifi_index = ifindex,
121 rta_info = znl_rta_nested_push(zb, IFLA_LINKINFO);
122 znl_rta_push(zb, IFLA_INFO_KIND, "gre", 3);
123 rta_data = znl_rta_nested_push(zb, IFLA_INFO_DATA);
125 znl_rta_push_u32(zb, IFLA_GRE_LINK, link_index);
126 while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
127 if (rta->rta_type == IFLA_GRE_LINK)
129 len = zbuf_used(&rtapl);
130 znl_rta_push(zb, rta->rta_type, zbuf_pulln(&rtapl, len), len);
133 znl_rta_nested_complete(zb, rta_data);
134 znl_rta_nested_complete(zb, rta_info);
136 znl_nlmsg_complete(zb, n);
137 zbuf_send(zb, netlink_req_fd);
138 zbuf_recv(zb, netlink_req_fd);