]> git.proxmox.com Git - mirror_frr.git/blame - nhrpd/netlink_gre.c
Merge pull request #5805 from donaldsharp/babel_int_return
[mirror_frr.git] / nhrpd / netlink_gre.c
CommitLineData
2fb975da
TT
1/* NHRP netlink/GRE tunnel configuration code
2 * Copyright (c) 2014-2016 Timo Teräs
3 *
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.
8 */
9
b45ac5f5
DL
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
836c52da 14#include <sys/socket.h>
2fb975da
TT
15#include <linux/netlink.h>
16#include <linux/rtnetlink.h>
836c52da 17#include <linux/in.h>
2fb975da
TT
18#include <linux/if.h>
19#include <linux/ip.h>
20#include <linux/ipv6.h>
21#include <linux/if_tunnel.h>
22
23#include "debug.h"
24#include "netlink.h"
25#include "znl.h"
26
996c9314
LB
27static int __netlink_gre_get_data(struct zbuf *zb, struct zbuf *data,
28 int ifindex)
2fb975da
TT
29{
30 struct nlmsghdr *n;
31 struct ifinfomsg *ifi;
32 struct zbuf payload, rtapayload;
33 struct rtattr *rta;
34
35 debugf(NHRP_DEBUG_KERNEL, "netlink-link-gre: get-info %u", ifindex);
36
37 n = znl_nlmsg_push(zb, RTM_GETLINK, NLM_F_REQUEST);
38 ifi = znl_push(zb, sizeof(*ifi));
996c9314 39 *ifi = (struct ifinfomsg){
2fb975da
TT
40 .ifi_index = ifindex,
41 };
42 znl_nlmsg_complete(zb, n);
43
996c9314
LB
44 if (zbuf_send(zb, netlink_req_fd) < 0
45 || zbuf_recv(zb, netlink_req_fd) < 0)
2fb975da
TT
46 return -1;
47
48 n = znl_nlmsg_pull(zb, &payload);
996c9314
LB
49 if (!n)
50 return -1;
2fb975da
TT
51
52 if (n->nlmsg_type != RTM_NEWLINK)
53 return -1;
54
55 ifi = znl_pull(&payload, sizeof(struct ifinfomsg));
56 if (!ifi)
57 return -1;
58
996c9314
LB
59 debugf(NHRP_DEBUG_KERNEL,
60 "netlink-link-gre: ifindex %u, receive msg_type %u, msg_flags %u",
61 ifi->ifi_index, n->nlmsg_type, n->nlmsg_flags);
2fb975da
TT
62
63 if (ifi->ifi_index != ifindex)
64 return -1;
65
66 while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
67 if (rta->rta_type == IFLA_LINKINFO)
68 break;
996c9314
LB
69 if (!rta)
70 return -1;
2fb975da
TT
71
72 payload = rtapayload;
73 while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
74 if (rta->rta_type == IFLA_INFO_DATA)
75 break;
996c9314
LB
76 if (!rta)
77 return -1;
2fb975da
TT
78
79 *data = rtapayload;
80 return 0;
81}
82
996c9314
LB
83void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key,
84 unsigned int *link_index, struct in_addr *saddr)
2fb975da
TT
85{
86 struct zbuf *zb = zbuf_alloc(8192), data, rtapl;
87 struct rtattr *rta;
88
89 *link_index = 0;
90 *gre_key = 0;
91 saddr->s_addr = 0;
92
93 if (__netlink_gre_get_data(zb, &data, ifindex) < 0)
94 goto err;
95
96 while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
97 switch (rta->rta_type) {
98 case IFLA_GRE_LINK:
99 *link_index = zbuf_get32(&rtapl);
100 break;
101 case IFLA_GRE_IKEY:
102 case IFLA_GRE_OKEY:
103 *gre_key = zbuf_get32(&rtapl);
104 break;
105 case IFLA_GRE_LOCAL:
106 saddr->s_addr = zbuf_get32(&rtapl);
107 break;
108 }
109 }
110err:
111 zbuf_free(zb);
112}
113
114void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index)
115{
116 struct nlmsghdr *n;
117 struct ifinfomsg *ifi;
118 struct rtattr *rta_info, *rta_data, *rta;
119 struct zbuf *zr = zbuf_alloc(8192), data, rtapl;
120 struct zbuf *zb = zbuf_alloc(8192);
121 size_t len;
122
123 if (__netlink_gre_get_data(zr, &data, ifindex) < 0)
124 goto err;
125
126 n = znl_nlmsg_push(zb, RTM_NEWLINK, NLM_F_REQUEST);
127 ifi = znl_push(zb, sizeof(*ifi));
996c9314 128 *ifi = (struct ifinfomsg){
2fb975da
TT
129 .ifi_index = ifindex,
130 };
131 rta_info = znl_rta_nested_push(zb, IFLA_LINKINFO);
132 znl_rta_push(zb, IFLA_INFO_KIND, "gre", 3);
133 rta_data = znl_rta_nested_push(zb, IFLA_INFO_DATA);
134
135 znl_rta_push_u32(zb, IFLA_GRE_LINK, link_index);
136 while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
137 if (rta->rta_type == IFLA_GRE_LINK)
138 continue;
139 len = zbuf_used(&rtapl);
140 znl_rta_push(zb, rta->rta_type, zbuf_pulln(&rtapl, len), len);
141 }
142
143 znl_rta_nested_complete(zb, rta_data);
144 znl_rta_nested_complete(zb, rta_info);
145
146 znl_nlmsg_complete(zb, n);
147 zbuf_send(zb, netlink_req_fd);
148 zbuf_recv(zb, netlink_req_fd);
149err:
150 zbuf_free(zb);
151 zbuf_free(zr);
152}