source: src/router/quagga/nhrpd/netlink_gre.c @ 31640

Last change on this file since 31640 was 31640, checked in by brainslayer, 3 months ago

update quagga

File size: 3.5 KB
Line 
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
10#include <sys/socket.h>
11#include <linux/netlink.h>
12#include <linux/rtnetlink.h>
13#include <linux/in.h>
14#include <linux/if.h>
15#include <linux/ip.h>
16#include <linux/ipv6.h>
17#include <linux/if_tunnel.h>
18
19#include "debug.h"
20#include "netlink.h"
21#include "znl.h"
22
23static int __netlink_gre_get_data(struct zbuf *zb, struct zbuf *data, int ifindex)
24{
25        struct nlmsghdr *n;
26        struct ifinfomsg *ifi;
27        struct zbuf payload, rtapayload;
28        struct rtattr *rta;
29
30        debugf(NHRP_DEBUG_KERNEL, "netlink-link-gre: get-info %u", ifindex);
31
32        n = znl_nlmsg_push(zb, RTM_GETLINK, NLM_F_REQUEST);
33        ifi = znl_push(zb, sizeof(*ifi));
34        *ifi = (struct ifinfomsg) {
35                .ifi_index = ifindex,
36        };
37        znl_nlmsg_complete(zb, n);
38
39        if (zbuf_send(zb, netlink_req_fd) < 0 ||
40            zbuf_recv(zb, netlink_req_fd) < 0)
41                return -1;
42
43        n = znl_nlmsg_pull(zb, &payload);
44        if (!n) return -1;
45
46        if (n->nlmsg_type != RTM_NEWLINK)
47                return -1;
48
49        ifi = znl_pull(&payload, sizeof(struct ifinfomsg));
50        if (!ifi)
51                return -1;
52
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);
55
56        if (ifi->ifi_index != ifindex)
57                return -1;
58
59        while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
60                if (rta->rta_type == IFLA_LINKINFO)
61                        break;
62        if (!rta) return -1;
63
64        payload = rtapayload;
65        while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
66                if (rta->rta_type == IFLA_INFO_DATA)
67                        break;
68        if (!rta) return -1;
69
70        *data = rtapayload;
71        return 0;
72}
73
74void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key, unsigned int *link_index, struct in_addr *saddr)
75{
76        struct zbuf *zb = zbuf_alloc(8192), data, rtapl;
77        struct rtattr *rta;
78
79        *link_index = 0;
80        *gre_key = 0;
81        saddr->s_addr = 0;
82
83        if (__netlink_gre_get_data(zb, &data, ifindex) < 0)
84                goto err;
85
86        while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
87                switch (rta->rta_type) {
88                case IFLA_GRE_LINK:
89                        *link_index = zbuf_get32(&rtapl);
90                        break;
91                case IFLA_GRE_IKEY:
92                case IFLA_GRE_OKEY:
93                        *gre_key = zbuf_get32(&rtapl);
94                        break;
95                case IFLA_GRE_LOCAL:
96                        saddr->s_addr = zbuf_get32(&rtapl);
97                        break;
98                }
99        }
100err:
101        zbuf_free(zb);
102}
103
104void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index)
105{
106        struct nlmsghdr *n;
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);
111        size_t len;
112
113        if (__netlink_gre_get_data(zr, &data, ifindex) < 0)
114                goto err;
115
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,
120        };
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);
124
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)
128                        continue;
129                len = zbuf_used(&rtapl);
130                znl_rta_push(zb, rta->rta_type, zbuf_pulln(&rtapl, len), len);
131        }
132
133        znl_rta_nested_complete(zb, rta_data);
134        znl_rta_nested_complete(zb, rta_info);
135
136        znl_nlmsg_complete(zb, n);
137        zbuf_send(zb, netlink_req_fd);
138        zbuf_recv(zb, netlink_req_fd);
139err:
140        zbuf_free(zb);
141        zbuf_free(zr);
142}
Note: See TracBrowser for help on using the repository browser.