]>
Commit | Line | Data |
---|---|---|
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 |
27 | static 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 |
83 | void 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 | } | |
110 | err: | |
111 | zbuf_free(zb); | |
112 | } | |
113 | ||
114 | void 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); | |
149 | err: | |
150 | zbuf_free(zb); | |
151 | zbuf_free(zr); | |
152 | } |