Blame


1 6b5c4000 2026-03-02 rsadowski /* $OpenBSD: pfe_route.c,v 1.15 2026/03/02 19:28:01 rsadowski Exp $ */
2 39bc6125 2009-08-13 reyk
3 39bc6125 2009-08-13 reyk /*
4 dc2f787f 2014-06-25 reyk * Copyright (c) 2009 - 2011 Reyk Floeter <reyk@openbsd.org>
5 39bc6125 2009-08-13 reyk *
6 39bc6125 2009-08-13 reyk * Permission to use, copy, modify, and distribute this software for any
7 39bc6125 2009-08-13 reyk * purpose with or without fee is hereby granted, provided that the above
8 39bc6125 2009-08-13 reyk * copyright notice and this permission notice appear in all copies.
9 39bc6125 2009-08-13 reyk *
10 39bc6125 2009-08-13 reyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 39bc6125 2009-08-13 reyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 39bc6125 2009-08-13 reyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 39bc6125 2009-08-13 reyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 39bc6125 2009-08-13 reyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 39bc6125 2009-08-13 reyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 39bc6125 2009-08-13 reyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 39bc6125 2009-08-13 reyk */
18 39bc6125 2009-08-13 reyk
19 39bc6125 2009-08-13 reyk #include <sys/types.h>
20 39bc6125 2009-08-13 reyk #include <sys/queue.h>
21 39bc6125 2009-08-13 reyk #include <sys/socket.h>
22 7afbe987 2023-06-29 claudio #include <sys/uio.h>
23 39bc6125 2009-08-13 reyk
24 39bc6125 2009-08-13 reyk #include <netinet/in.h>
25 39bc6125 2009-08-13 reyk #include <net/route.h>
26 d93c36af 2015-01-22 reyk #include <arpa/inet.h>
27 39bc6125 2009-08-13 reyk
28 d93c36af 2015-01-22 reyk #include <limits.h>
29 7afbe987 2023-06-29 claudio #include <stddef.h>
30 39bc6125 2009-08-13 reyk #include <stdio.h>
31 39bc6125 2009-08-13 reyk #include <unistd.h>
32 39bc6125 2009-08-13 reyk #include <string.h>
33 39bc6125 2009-08-13 reyk #include <errno.h>
34 39bc6125 2009-08-13 reyk
35 39bc6125 2009-08-13 reyk #include "relayd.h"
36 6b5c4000 2026-03-02 rsadowski #include "log.h"
37 39bc6125 2009-08-13 reyk
38 39bc6125 2009-08-13 reyk void
39 39bc6125 2009-08-13 reyk init_routes(struct relayd *env)
40 39bc6125 2009-08-13 reyk {
41 39bc6125 2009-08-13 reyk u_int rtfilter;
42 39bc6125 2009-08-13 reyk
43 58fc320c 2016-09-02 reyk if (!(env->sc_conf.flags & F_NEEDRT))
44 39bc6125 2009-08-13 reyk return;
45 39bc6125 2009-08-13 reyk
46 39bc6125 2009-08-13 reyk if ((env->sc_rtsock = socket(AF_ROUTE, SOCK_RAW, 0)) == -1)
47 09e53fee 2017-05-28 benno fatal("%s: failed to open routing socket", __func__);
48 39bc6125 2009-08-13 reyk
49 39bc6125 2009-08-13 reyk rtfilter = ROUTE_FILTER(0);
50 39bc6125 2009-08-13 reyk if (setsockopt(env->sc_rtsock, AF_ROUTE, ROUTE_MSGFILTER,
51 39bc6125 2009-08-13 reyk &rtfilter, sizeof(rtfilter)) == -1)
52 09e53fee 2017-05-28 benno fatal("%s: ROUTE_MSGFILTER", __func__);
53 39bc6125 2009-08-13 reyk }
54 39bc6125 2009-08-13 reyk
55 39bc6125 2009-08-13 reyk void
56 39bc6125 2009-08-13 reyk sync_routes(struct relayd *env, struct router *rt)
57 39bc6125 2009-08-13 reyk {
58 39bc6125 2009-08-13 reyk struct netroute *nr;
59 39bc6125 2009-08-13 reyk struct host *host;
60 2f6ec04d 2015-01-16 deraadt char buf[HOST_NAME_MAX+1];
61 39bc6125 2009-08-13 reyk struct ctl_netroute crt;
62 39bc6125 2009-08-13 reyk
63 58fc320c 2016-09-02 reyk if (!(env->sc_conf.flags & F_NEEDRT))
64 39bc6125 2009-08-13 reyk return;
65 39bc6125 2009-08-13 reyk
66 39bc6125 2009-08-13 reyk TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry) {
67 39bc6125 2009-08-13 reyk print_host(&nr->nr_conf.ss, buf, sizeof(buf));
68 39bc6125 2009-08-13 reyk TAILQ_FOREACH(host, &rt->rt_gwtable->hosts, entry) {
69 39bc6125 2009-08-13 reyk if (host->up == HOST_UNKNOWN)
70 39bc6125 2009-08-13 reyk continue;
71 39bc6125 2009-08-13 reyk
72 666bd316 2011-05-05 reyk log_debug("%s: "
73 246e5b16 2011-05-05 phessler "router %s route %s/%d gateway %s %s priority %d",
74 666bd316 2011-05-05 reyk __func__,
75 39bc6125 2009-08-13 reyk rt->rt_conf.name, buf, nr->nr_conf.prefixlen,
76 39bc6125 2009-08-13 reyk host->conf.name,
77 246e5b16 2011-05-05 phessler HOST_ISUP(host->up) ? "up" : "down",
78 246e5b16 2011-05-05 phessler host->conf.priority);
79 39bc6125 2009-08-13 reyk
80 39bc6125 2009-08-13 reyk crt.up = host->up;
81 591e6ab5 2011-05-19 reyk memcpy(&crt.nr, &nr->nr_conf, sizeof(nr->nr_conf));
82 591e6ab5 2011-05-19 reyk memcpy(&crt.host, &host->conf, sizeof(host->conf));
83 591e6ab5 2011-05-19 reyk memcpy(&crt.rt, &rt->rt_conf, sizeof(rt->rt_conf));
84 39bc6125 2009-08-13 reyk
85 141b9058 2015-12-02 reyk proc_compose(env->sc_ps, PROC_PARENT,
86 141b9058 2015-12-02 reyk IMSG_RTMSG, &crt, sizeof(crt));
87 39bc6125 2009-08-13 reyk }
88 39bc6125 2009-08-13 reyk }
89 39bc6125 2009-08-13 reyk }
90 39bc6125 2009-08-13 reyk
91 7afbe987 2023-06-29 claudio static void
92 7afbe987 2023-06-29 claudio pfe_apply_prefixlen(struct sockaddr_storage *ss, int af, int len)
93 7afbe987 2023-06-29 claudio {
94 7afbe987 2023-06-29 claudio int q, r, off;
95 7afbe987 2023-06-29 claudio uint8_t *b = (uint8_t *)ss;
96 7afbe987 2023-06-29 claudio
97 5b68d4ba 2023-06-29 claudio q = len >> 3;
98 7afbe987 2023-06-29 claudio r = len & 7;
99 7afbe987 2023-06-29 claudio
100 7afbe987 2023-06-29 claudio bzero(ss, sizeof(*ss));
101 7afbe987 2023-06-29 claudio ss->ss_family = af;
102 7afbe987 2023-06-29 claudio switch (af) {
103 7afbe987 2023-06-29 claudio case AF_INET:
104 7afbe987 2023-06-29 claudio ss->ss_len = sizeof(struct sockaddr_in);
105 7afbe987 2023-06-29 claudio off = offsetof(struct sockaddr_in, sin_addr);
106 7afbe987 2023-06-29 claudio break;
107 7afbe987 2023-06-29 claudio case AF_INET6:
108 7afbe987 2023-06-29 claudio ss->ss_len = sizeof(struct sockaddr_in6);
109 7afbe987 2023-06-29 claudio off = offsetof(struct sockaddr_in6, sin6_addr);
110 7afbe987 2023-06-29 claudio break;
111 7afbe987 2023-06-29 claudio default:
112 7afbe987 2023-06-29 claudio fatal("%s: invalid address family", __func__);
113 7afbe987 2023-06-29 claudio }
114 7afbe987 2023-06-29 claudio if (q > 0)
115 7afbe987 2023-06-29 claudio memset(b + off, 0xff, q);
116 7afbe987 2023-06-29 claudio if (r > 0)
117 7afbe987 2023-06-29 claudio b[off + q] = (0xff00 >> r) & 0xff;
118 7afbe987 2023-06-29 claudio }
119 7afbe987 2023-06-29 claudio
120 7afbe987 2023-06-29 claudio #define ROUNDUP(a) \
121 7afbe987 2023-06-29 claudio ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
122 7afbe987 2023-06-29 claudio
123 39bc6125 2009-08-13 reyk int
124 39bc6125 2009-08-13 reyk pfe_route(struct relayd *env, struct ctl_netroute *crt)
125 39bc6125 2009-08-13 reyk {
126 7afbe987 2023-06-29 claudio struct iovec iov[5];
127 7afbe987 2023-06-29 claudio struct rt_msghdr hdr;
128 7afbe987 2023-06-29 claudio struct sockaddr_storage dst, gw, mask, label;
129 7afbe987 2023-06-29 claudio struct sockaddr_rtlabel *sr = (struct sockaddr_rtlabel *)&label;
130 7afbe987 2023-06-29 claudio int iovcnt = 0;
131 39bc6125 2009-08-13 reyk char *gwname;
132 39bc6125 2009-08-13 reyk
133 7afbe987 2023-06-29 claudio bzero(&hdr, sizeof(hdr));
134 7afbe987 2023-06-29 claudio hdr.rtm_msglen = sizeof(hdr);
135 7afbe987 2023-06-29 claudio hdr.rtm_version = RTM_VERSION;
136 7afbe987 2023-06-29 claudio hdr.rtm_type = HOST_ISUP(crt->up) ? RTM_ADD : RTM_DELETE;
137 7afbe987 2023-06-29 claudio hdr.rtm_flags = RTF_STATIC | RTF_GATEWAY | RTF_MPATH;
138 7afbe987 2023-06-29 claudio hdr.rtm_seq = env->sc_rtseq++;
139 7afbe987 2023-06-29 claudio hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
140 7afbe987 2023-06-29 claudio hdr.rtm_tableid = crt->rt.rtable;
141 7afbe987 2023-06-29 claudio hdr.rtm_priority = crt->host.priority;
142 7afbe987 2023-06-29 claudio
143 7afbe987 2023-06-29 claudio iov[iovcnt].iov_base = &hdr;
144 7afbe987 2023-06-29 claudio iov[iovcnt++].iov_len = sizeof(hdr);
145 7afbe987 2023-06-29 claudio
146 7afbe987 2023-06-29 claudio dst = crt->nr.ss;
147 7afbe987 2023-06-29 claudio gw = crt->host.ss;
148 591e6ab5 2011-05-19 reyk gwname = crt->host.name;
149 7afbe987 2023-06-29 claudio pfe_apply_prefixlen(&mask, dst.ss_family, crt->nr.prefixlen);
150 39bc6125 2009-08-13 reyk
151 7afbe987 2023-06-29 claudio iov[iovcnt].iov_base = &dst;
152 7afbe987 2023-06-29 claudio iov[iovcnt++].iov_len = ROUNDUP(dst.ss_len);
153 7afbe987 2023-06-29 claudio hdr.rtm_msglen += ROUNDUP(dst.ss_len);
154 39bc6125 2009-08-13 reyk
155 7afbe987 2023-06-29 claudio iov[iovcnt].iov_base = &gw;
156 7afbe987 2023-06-29 claudio iov[iovcnt++].iov_len = ROUNDUP(gw.ss_len);
157 7afbe987 2023-06-29 claudio hdr.rtm_msglen += ROUNDUP(gw.ss_len);
158 39bc6125 2009-08-13 reyk
159 7afbe987 2023-06-29 claudio iov[iovcnt].iov_base = &mask;
160 7afbe987 2023-06-29 claudio iov[iovcnt++].iov_len = ROUNDUP(mask.ss_len);
161 7afbe987 2023-06-29 claudio hdr.rtm_msglen += ROUNDUP(mask.ss_len);
162 7afbe987 2023-06-29 claudio
163 591e6ab5 2011-05-19 reyk if (strlen(crt->rt.label)) {
164 7afbe987 2023-06-29 claudio sr->sr_len = sizeof(*sr);
165 7afbe987 2023-06-29 claudio strlcpy(sr->sr_label, crt->rt.label, sizeof(sr->sr_label));
166 7afbe987 2023-06-29 claudio
167 7afbe987 2023-06-29 claudio iov[iovcnt].iov_base = &label;
168 7afbe987 2023-06-29 claudio iov[iovcnt++].iov_len = ROUNDUP(label.ss_len);
169 7afbe987 2023-06-29 claudio hdr.rtm_msglen += ROUNDUP(label.ss_len);
170 7afbe987 2023-06-29 claudio hdr.rtm_addrs |= RTA_LABEL;
171 39bc6125 2009-08-13 reyk }
172 39bc6125 2009-08-13 reyk
173 39bc6125 2009-08-13 reyk retry:
174 7afbe987 2023-06-29 claudio if (writev(env->sc_rtsock, iov, iovcnt) == -1) {
175 39bc6125 2009-08-13 reyk switch (errno) {
176 39bc6125 2009-08-13 reyk case EEXIST:
177 39bc6125 2009-08-13 reyk case ESRCH:
178 7afbe987 2023-06-29 claudio if (hdr.rtm_type == RTM_ADD) {
179 7afbe987 2023-06-29 claudio hdr.rtm_type = RTM_CHANGE;
180 39bc6125 2009-08-13 reyk goto retry;
181 7afbe987 2023-06-29 claudio } else if (hdr.rtm_type == RTM_DELETE) {
182 39bc6125 2009-08-13 reyk /* Ignore */
183 39bc6125 2009-08-13 reyk break;
184 39bc6125 2009-08-13 reyk }
185 39bc6125 2009-08-13 reyk /* FALLTHROUGH */
186 39bc6125 2009-08-13 reyk default:
187 39bc6125 2009-08-13 reyk goto bad;
188 39bc6125 2009-08-13 reyk }
189 39bc6125 2009-08-13 reyk }
190 39bc6125 2009-08-13 reyk
191 666bd316 2011-05-05 reyk log_debug("%s: gateway %s %s", __func__, gwname,
192 39bc6125 2009-08-13 reyk HOST_ISUP(crt->up) ? "added" : "deleted");
193 39bc6125 2009-08-13 reyk
194 39bc6125 2009-08-13 reyk return (0);
195 39bc6125 2009-08-13 reyk
196 39bc6125 2009-08-13 reyk bad:
197 666bd316 2011-05-05 reyk log_debug("%s: failed to %s gateway %s: %d %s", __func__,
198 39bc6125 2009-08-13 reyk HOST_ISUP(crt->up) ? "add" : "delete", gwname,
199 39bc6125 2009-08-13 reyk errno, strerror(errno));
200 39bc6125 2009-08-13 reyk
201 39bc6125 2009-08-13 reyk return (-1);
202 39bc6125 2009-08-13 reyk }