| @@ -1,1573 +1,1569 @@ | | | @@ -1,1573 +1,1569 @@ |
1 | /* $NetBSD: rtsock.c,v 1.213 2017/06/01 02:45:14 chs Exp $ */ | | 1 | /* $NetBSD: rtsock.c,v 1.214 2017/06/15 02:51:45 ozaki-r Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of the project nor the names of its contributors | | 15 | * 3. Neither the name of the project nor the names of its contributors |
16 | * may be used to endorse or promote products derived from this software | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | | 19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Copyright (c) 1988, 1991, 1993 | | 33 | * Copyright (c) 1988, 1991, 1993 |
34 | * The Regents of the University of California. All rights reserved. | | 34 | * The Regents of the University of California. All rights reserved. |
35 | * | | 35 | * |
36 | * Redistribution and use in source and binary forms, with or without | | 36 | * Redistribution and use in source and binary forms, with or without |
37 | * modification, are permitted provided that the following conditions | | 37 | * modification, are permitted provided that the following conditions |
38 | * are met: | | 38 | * are met: |
39 | * 1. Redistributions of source code must retain the above copyright | | 39 | * 1. Redistributions of source code must retain the above copyright |
40 | * notice, this list of conditions and the following disclaimer. | | 40 | * notice, this list of conditions and the following disclaimer. |
41 | * 2. Redistributions in binary form must reproduce the above copyright | | 41 | * 2. Redistributions in binary form must reproduce the above copyright |
42 | * notice, this list of conditions and the following disclaimer in the | | 42 | * notice, this list of conditions and the following disclaimer in the |
43 | * documentation and/or other materials provided with the distribution. | | 43 | * documentation and/or other materials provided with the distribution. |
44 | * 3. Neither the name of the University nor the names of its contributors | | 44 | * 3. Neither the name of the University nor the names of its contributors |
45 | * may be used to endorse or promote products derived from this software | | 45 | * may be used to endorse or promote products derived from this software |
46 | * without specific prior written permission. | | 46 | * without specific prior written permission. |
47 | * | | 47 | * |
48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
58 | * SUCH DAMAGE. | | 58 | * SUCH DAMAGE. |
59 | * | | 59 | * |
60 | * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 | | 60 | * @(#)rtsock.c 8.7 (Berkeley) 10/12/95 |
61 | */ | | 61 | */ |
62 | | | 62 | |
63 | #include <sys/cdefs.h> | | 63 | #include <sys/cdefs.h> |
64 | __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.213 2017/06/01 02:45:14 chs Exp $"); | | 64 | __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.214 2017/06/15 02:51:45 ozaki-r Exp $"); |
65 | | | 65 | |
66 | #ifdef _KERNEL_OPT | | 66 | #ifdef _KERNEL_OPT |
67 | #include "opt_inet.h" | | 67 | #include "opt_inet.h" |
68 | #include "opt_mpls.h" | | 68 | #include "opt_mpls.h" |
69 | #include "opt_compat_netbsd.h" | | 69 | #include "opt_compat_netbsd.h" |
70 | #include "opt_sctp.h" | | 70 | #include "opt_sctp.h" |
71 | #include "opt_net_mpsafe.h" | | 71 | #include "opt_net_mpsafe.h" |
72 | #endif | | 72 | #endif |
73 | | | 73 | |
74 | #include <sys/param.h> | | 74 | #include <sys/param.h> |
75 | #include <sys/systm.h> | | 75 | #include <sys/systm.h> |
76 | #include <sys/proc.h> | | 76 | #include <sys/proc.h> |
77 | #include <sys/socket.h> | | 77 | #include <sys/socket.h> |
78 | #include <sys/socketvar.h> | | 78 | #include <sys/socketvar.h> |
79 | #include <sys/domain.h> | | 79 | #include <sys/domain.h> |
80 | #include <sys/protosw.h> | | 80 | #include <sys/protosw.h> |
81 | #include <sys/sysctl.h> | | 81 | #include <sys/sysctl.h> |
82 | #include <sys/kauth.h> | | 82 | #include <sys/kauth.h> |
83 | #include <sys/kmem.h> | | 83 | #include <sys/kmem.h> |
84 | #include <sys/intr.h> | | 84 | #include <sys/intr.h> |
85 | | | 85 | |
86 | #include <net/if.h> | | 86 | #include <net/if.h> |
87 | #include <net/if_llatbl.h> | | 87 | #include <net/if_llatbl.h> |
88 | #include <net/if_types.h> | | 88 | #include <net/if_types.h> |
89 | #include <net/route.h> | | 89 | #include <net/route.h> |
90 | #include <net/raw_cb.h> | | 90 | #include <net/raw_cb.h> |
91 | | | 91 | |
92 | #include <netinet/in_var.h> | | 92 | #include <netinet/in_var.h> |
93 | #include <netinet/if_inarp.h> | | 93 | #include <netinet/if_inarp.h> |
94 | | | 94 | |
95 | #include <netmpls/mpls.h> | | 95 | #include <netmpls/mpls.h> |
96 | | | 96 | |
97 | #ifdef SCTP | | 97 | #ifdef SCTP |
98 | extern void sctp_add_ip_address(struct ifaddr *); | | 98 | extern void sctp_add_ip_address(struct ifaddr *); |
99 | extern void sctp_delete_ip_address(struct ifaddr *); | | 99 | extern void sctp_delete_ip_address(struct ifaddr *); |
100 | #endif | | 100 | #endif |
101 | | | 101 | |
102 | #if defined(COMPAT_14) || defined(COMPAT_50) || defined(COMPAT_70) | | 102 | #if defined(COMPAT_14) || defined(COMPAT_50) || defined(COMPAT_70) |
103 | #include <compat/net/if.h> | | 103 | #include <compat/net/if.h> |
104 | #include <compat/net/route.h> | | 104 | #include <compat/net/route.h> |
105 | #endif | | 105 | #endif |
106 | #ifdef COMPAT_RTSOCK | | 106 | #ifdef COMPAT_RTSOCK |
107 | #define RTM_XVERSION RTM_OVERSION | | 107 | #define RTM_XVERSION RTM_OVERSION |
108 | #define RTM_XNEWADDR RTM_ONEWADDR | | 108 | #define RTM_XNEWADDR RTM_ONEWADDR |
109 | #define RTM_XDELADDR RTM_ODELADDR | | 109 | #define RTM_XDELADDR RTM_ODELADDR |
110 | #define RTM_XCHGADDR RTM_OCHGADDR | | 110 | #define RTM_XCHGADDR RTM_OCHGADDR |
111 | #define RT_XADVANCE(a,b) RT_OADVANCE(a,b) | | 111 | #define RT_XADVANCE(a,b) RT_OADVANCE(a,b) |
112 | #define RT_XROUNDUP(n) RT_OROUNDUP(n) | | 112 | #define RT_XROUNDUP(n) RT_OROUNDUP(n) |
113 | #define PF_XROUTE PF_OROUTE | | 113 | #define PF_XROUTE PF_OROUTE |
114 | #define rt_xmsghdr rt_msghdr50 | | 114 | #define rt_xmsghdr rt_msghdr50 |
115 | #define if_xmsghdr if_msghdr /* if_msghdr50 is for RTM_OIFINFO */ | | 115 | #define if_xmsghdr if_msghdr /* if_msghdr50 is for RTM_OIFINFO */ |
116 | #define ifa_xmsghdr ifa_msghdr50 | | 116 | #define ifa_xmsghdr ifa_msghdr50 |
117 | #define if_xannouncemsghdr if_announcemsghdr50 | | 117 | #define if_xannouncemsghdr if_announcemsghdr50 |
118 | #define COMPATNAME(x) compat_50_ ## x | | 118 | #define COMPATNAME(x) compat_50_ ## x |
119 | #define DOMAINNAME "oroute" | | 119 | #define DOMAINNAME "oroute" |
120 | CTASSERT(sizeof(struct ifa_xmsghdr) == 20); | | 120 | CTASSERT(sizeof(struct ifa_xmsghdr) == 20); |
121 | DOMAIN_DEFINE(compat_50_routedomain); /* forward declare and add to link set */ | | 121 | DOMAIN_DEFINE(compat_50_routedomain); /* forward declare and add to link set */ |
122 | #undef COMPAT_70 | | 122 | #undef COMPAT_70 |
123 | #else /* COMPAT_RTSOCK */ | | 123 | #else /* COMPAT_RTSOCK */ |
124 | #define RTM_XVERSION RTM_VERSION | | 124 | #define RTM_XVERSION RTM_VERSION |
125 | #define RTM_XNEWADDR RTM_NEWADDR | | 125 | #define RTM_XNEWADDR RTM_NEWADDR |
126 | #define RTM_XDELADDR RTM_DELADDR | | 126 | #define RTM_XDELADDR RTM_DELADDR |
127 | #define RTM_XCHGADDR RTM_CHGADDR | | 127 | #define RTM_XCHGADDR RTM_CHGADDR |
128 | #define RT_XADVANCE(a,b) RT_ADVANCE(a,b) | | 128 | #define RT_XADVANCE(a,b) RT_ADVANCE(a,b) |
129 | #define RT_XROUNDUP(n) RT_ROUNDUP(n) | | 129 | #define RT_XROUNDUP(n) RT_ROUNDUP(n) |
130 | #define PF_XROUTE PF_ROUTE | | 130 | #define PF_XROUTE PF_ROUTE |
131 | #define rt_xmsghdr rt_msghdr | | 131 | #define rt_xmsghdr rt_msghdr |
132 | #define if_xmsghdr if_msghdr | | 132 | #define if_xmsghdr if_msghdr |
133 | #define ifa_xmsghdr ifa_msghdr | | 133 | #define ifa_xmsghdr ifa_msghdr |
134 | #define if_xannouncemsghdr if_announcemsghdr | | 134 | #define if_xannouncemsghdr if_announcemsghdr |
135 | #define COMPATNAME(x) x | | 135 | #define COMPATNAME(x) x |
136 | #define DOMAINNAME "route" | | 136 | #define DOMAINNAME "route" |
137 | CTASSERT(sizeof(struct ifa_xmsghdr) == 32); | | 137 | CTASSERT(sizeof(struct ifa_xmsghdr) == 32); |
138 | #ifdef COMPAT_50 | | 138 | #ifdef COMPAT_50 |
139 | #define COMPATCALL(name, args) compat_50_ ## name args | | 139 | #define COMPATCALL(name, args) compat_50_ ## name args |
140 | #endif | | 140 | #endif |
141 | DOMAIN_DEFINE(routedomain); /* forward declare and add to link set */ | | 141 | DOMAIN_DEFINE(routedomain); /* forward declare and add to link set */ |
142 | #undef COMPAT_50 | | 142 | #undef COMPAT_50 |
143 | #undef COMPAT_14 | | 143 | #undef COMPAT_14 |
144 | #endif /* COMPAT_RTSOCK */ | | 144 | #endif /* COMPAT_RTSOCK */ |
145 | | | 145 | |
146 | #ifndef COMPATCALL | | 146 | #ifndef COMPATCALL |
147 | #define COMPATCALL(name, args) do { } while (/*CONSTCOND*/ 0) | | 147 | #define COMPATCALL(name, args) do { } while (/*CONSTCOND*/ 0) |
148 | #endif | | 148 | #endif |
149 | | | 149 | |
150 | #ifdef RTSOCK_DEBUG | | 150 | #ifdef RTSOCK_DEBUG |
151 | #define RT_IN_PRINT(info, b, a) (in_print((b), sizeof(b), \ | | 151 | #define RT_IN_PRINT(info, b, a) (in_print((b), sizeof(b), \ |
152 | &((const struct sockaddr_in *)(info)->rti_info[(a)])->sin_addr), (b)) | | 152 | &((const struct sockaddr_in *)(info)->rti_info[(a)])->sin_addr), (b)) |
153 | #endif /* RTSOCK_DEBUG */ | | 153 | #endif /* RTSOCK_DEBUG */ |
154 | | | 154 | |
155 | struct route_info COMPATNAME(route_info) = { | | 155 | struct route_info COMPATNAME(route_info) = { |
156 | .ri_dst = { .sa_len = 2, .sa_family = PF_XROUTE, }, | | 156 | .ri_dst = { .sa_len = 2, .sa_family = PF_XROUTE, }, |
157 | .ri_src = { .sa_len = 2, .sa_family = PF_XROUTE, }, | | 157 | .ri_src = { .sa_len = 2, .sa_family = PF_XROUTE, }, |
158 | .ri_maxqlen = IFQ_MAXLEN, | | 158 | .ri_maxqlen = IFQ_MAXLEN, |
159 | }; | | 159 | }; |
160 | | | 160 | |
161 | #define PRESERVED_RTF (RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_DONE | RTF_MASK) | | 161 | #define PRESERVED_RTF (RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_DONE | RTF_MASK) |
162 | | | 162 | |
163 | static void COMPATNAME(route_init)(void); | | 163 | static void COMPATNAME(route_init)(void); |
164 | static int COMPATNAME(route_output)(struct mbuf *, struct socket *); | | 164 | static int COMPATNAME(route_output)(struct mbuf *, struct socket *); |
165 | | | 165 | |
166 | static int rt_xaddrs(u_char, const char *, const char *, struct rt_addrinfo *); | | 166 | static int rt_xaddrs(u_char, const char *, const char *, struct rt_addrinfo *); |
167 | static struct mbuf *rt_makeifannouncemsg(struct ifnet *, int, int, | | 167 | static struct mbuf *rt_makeifannouncemsg(struct ifnet *, int, int, |
168 | struct rt_addrinfo *); | | 168 | struct rt_addrinfo *); |
169 | static int rt_msg2(int, struct rt_addrinfo *, void *, struct rt_walkarg *, int *); | | 169 | static int rt_msg2(int, struct rt_addrinfo *, void *, struct rt_walkarg *, int *); |
170 | static void rt_setmetrics(int, const struct rt_xmsghdr *, struct rtentry *); | | 170 | static void rt_setmetrics(int, const struct rt_xmsghdr *, struct rtentry *); |
171 | static void rtm_setmetrics(const struct rtentry *, struct rt_xmsghdr *); | | 171 | static void rtm_setmetrics(const struct rtentry *, struct rt_xmsghdr *); |
172 | static void sysctl_net_route_setup(struct sysctllog **); | | 172 | static void sysctl_net_route_setup(struct sysctllog **); |
173 | static int sysctl_dumpentry(struct rtentry *, void *); | | 173 | static int sysctl_dumpentry(struct rtentry *, void *); |
174 | static int sysctl_iflist(int, struct rt_walkarg *, int); | | 174 | static int sysctl_iflist(int, struct rt_walkarg *, int); |
175 | static int sysctl_rtable(SYSCTLFN_PROTO); | | 175 | static int sysctl_rtable(SYSCTLFN_PROTO); |
176 | static void rt_adjustcount(int, int); | | 176 | static void rt_adjustcount(int, int); |
177 | | | 177 | |
178 | static const struct protosw COMPATNAME(route_protosw)[]; | | 178 | static const struct protosw COMPATNAME(route_protosw)[]; |
179 | | | 179 | |
180 | struct routecb { | | 180 | struct routecb { |
181 | struct rawcb rocb_rcb; | | 181 | struct rawcb rocb_rcb; |
182 | unsigned int rocb_msgfilter; | | 182 | unsigned int rocb_msgfilter; |
183 | #define RTMSGFILTER(m) (1U << (m)) | | 183 | #define RTMSGFILTER(m) (1U << (m)) |
184 | }; | | 184 | }; |
185 | #define sotoroutecb(so) ((struct routecb *)(so)->so_pcb) | | 185 | #define sotoroutecb(so) ((struct routecb *)(so)->so_pcb) |
186 | | | 186 | |
187 | static void | | 187 | static void |
188 | rt_adjustcount(int af, int cnt) | | 188 | rt_adjustcount(int af, int cnt) |
189 | { | | 189 | { |
190 | struct route_cb * const cb = &COMPATNAME(route_info).ri_cb; | | 190 | struct route_cb * const cb = &COMPATNAME(route_info).ri_cb; |
191 | | | 191 | |
192 | cb->any_count += cnt; | | 192 | cb->any_count += cnt; |
193 | | | 193 | |
194 | switch (af) { | | 194 | switch (af) { |
195 | case AF_INET: | | 195 | case AF_INET: |
196 | cb->ip_count += cnt; | | 196 | cb->ip_count += cnt; |
197 | return; | | 197 | return; |
198 | #ifdef INET6 | | 198 | #ifdef INET6 |
199 | case AF_INET6: | | 199 | case AF_INET6: |
200 | cb->ip6_count += cnt; | | 200 | cb->ip6_count += cnt; |
201 | return; | | 201 | return; |
202 | #endif | | 202 | #endif |
203 | case AF_MPLS: | | 203 | case AF_MPLS: |
204 | cb->mpls_count += cnt; | | 204 | cb->mpls_count += cnt; |
205 | return; | | 205 | return; |
206 | } | | 206 | } |
207 | } | | 207 | } |
208 | | | 208 | |
209 | static int | | 209 | static int |
210 | COMPATNAME(route_filter)(struct mbuf *m, struct sockproto *proto, | | 210 | COMPATNAME(route_filter)(struct mbuf *m, struct sockproto *proto, |
211 | struct rawcb *rp) | | 211 | struct rawcb *rp) |
212 | { | | 212 | { |
213 | struct routecb *rop = (struct routecb *)rp; | | 213 | struct routecb *rop = (struct routecb *)rp; |
214 | struct rt_xmsghdr *rtm; | | 214 | struct rt_xmsghdr *rtm; |
215 | | | 215 | |
216 | KASSERT(m != NULL); | | 216 | KASSERT(m != NULL); |
217 | KASSERT(proto != NULL); | | 217 | KASSERT(proto != NULL); |
218 | KASSERT(rp != NULL); | | 218 | KASSERT(rp != NULL); |
219 | | | 219 | |
220 | /* Wrong family for this socket. */ | | 220 | /* Wrong family for this socket. */ |
221 | if (proto->sp_family != PF_ROUTE) | | 221 | if (proto->sp_family != PF_ROUTE) |
222 | return ENOPROTOOPT; | | 222 | return ENOPROTOOPT; |
223 | | | 223 | |
224 | /* If no filter set, just return. */ | | 224 | /* If no filter set, just return. */ |
225 | if (rop->rocb_msgfilter == 0) | | 225 | if (rop->rocb_msgfilter == 0) |
226 | return 0; | | 226 | return 0; |
227 | | | 227 | |
228 | /* Ensure we can access rtm_type */ | | 228 | /* Ensure we can access rtm_type */ |
229 | if (m->m_len < | | 229 | if (m->m_len < |
230 | offsetof(struct rt_xmsghdr, rtm_type) + sizeof(rtm->rtm_type)) | | 230 | offsetof(struct rt_xmsghdr, rtm_type) + sizeof(rtm->rtm_type)) |
231 | return EINVAL; | | 231 | return EINVAL; |
232 | | | 232 | |
233 | rtm = mtod(m, struct rt_xmsghdr *); | | 233 | rtm = mtod(m, struct rt_xmsghdr *); |
234 | /* If the rtm type is filtered out, return a positive. */ | | 234 | /* If the rtm type is filtered out, return a positive. */ |
235 | if (!(rop->rocb_msgfilter & RTMSGFILTER(rtm->rtm_type))) | | 235 | if (!(rop->rocb_msgfilter & RTMSGFILTER(rtm->rtm_type))) |
236 | return EEXIST; | | 236 | return EEXIST; |
237 | | | 237 | |
238 | /* Passed the filter. */ | | 238 | /* Passed the filter. */ |
239 | return 0; | | 239 | return 0; |
240 | } | | 240 | } |
241 | | | 241 | |
242 | static int | | 242 | static int |
243 | COMPATNAME(route_attach)(struct socket *so, int proto) | | 243 | COMPATNAME(route_attach)(struct socket *so, int proto) |
244 | { | | 244 | { |
245 | struct rawcb *rp; | | 245 | struct rawcb *rp; |
246 | struct routecb *rop; | | 246 | struct routecb *rop; |
247 | int s, error; | | 247 | int s, error; |
248 | | | 248 | |
249 | KASSERT(sotorawcb(so) == NULL); | | 249 | KASSERT(sotorawcb(so) == NULL); |
250 | rop = kmem_zalloc(sizeof(*rop), KM_SLEEP); | | 250 | rop = kmem_zalloc(sizeof(*rop), KM_SLEEP); |
251 | rp = &rop->rocb_rcb; | | 251 | rp = &rop->rocb_rcb; |
252 | rp->rcb_len = sizeof(*rop); | | 252 | rp->rcb_len = sizeof(*rop); |
253 | so->so_pcb = rp; | | 253 | so->so_pcb = rp; |
254 | | | 254 | |
255 | s = splsoftnet(); | | 255 | s = splsoftnet(); |
256 | if ((error = raw_attach(so, proto)) == 0) { | | 256 | if ((error = raw_attach(so, proto)) == 0) { |
257 | rt_adjustcount(rp->rcb_proto.sp_protocol, 1); | | 257 | rt_adjustcount(rp->rcb_proto.sp_protocol, 1); |
258 | rp->rcb_laddr = &COMPATNAME(route_info).ri_src; | | 258 | rp->rcb_laddr = &COMPATNAME(route_info).ri_src; |
259 | rp->rcb_faddr = &COMPATNAME(route_info).ri_dst; | | 259 | rp->rcb_faddr = &COMPATNAME(route_info).ri_dst; |
260 | rp->rcb_filter = COMPATNAME(route_filter); | | 260 | rp->rcb_filter = COMPATNAME(route_filter); |
261 | } | | 261 | } |
262 | splx(s); | | 262 | splx(s); |
263 | | | 263 | |
264 | if (error) { | | 264 | if (error) { |
265 | kmem_free(rop, sizeof(*rop)); | | 265 | kmem_free(rop, sizeof(*rop)); |
266 | so->so_pcb = NULL; | | 266 | so->so_pcb = NULL; |
267 | return error; | | 267 | return error; |
268 | } | | 268 | } |
269 | | | 269 | |
270 | soisconnected(so); | | 270 | soisconnected(so); |
271 | so->so_options |= SO_USELOOPBACK; | | 271 | so->so_options |= SO_USELOOPBACK; |
272 | KASSERT(solocked(so)); | | 272 | KASSERT(solocked(so)); |
273 | | | 273 | |
274 | return error; | | 274 | return error; |
275 | } | | 275 | } |
276 | | | 276 | |
277 | static void | | 277 | static void |
278 | COMPATNAME(route_detach)(struct socket *so) | | 278 | COMPATNAME(route_detach)(struct socket *so) |
279 | { | | 279 | { |
280 | struct rawcb *rp = sotorawcb(so); | | 280 | struct rawcb *rp = sotorawcb(so); |
281 | int s; | | 281 | int s; |
282 | | | 282 | |
283 | KASSERT(rp != NULL); | | 283 | KASSERT(rp != NULL); |
284 | KASSERT(solocked(so)); | | 284 | KASSERT(solocked(so)); |
285 | | | 285 | |
286 | s = splsoftnet(); | | 286 | s = splsoftnet(); |
287 | rt_adjustcount(rp->rcb_proto.sp_protocol, -1); | | 287 | rt_adjustcount(rp->rcb_proto.sp_protocol, -1); |
288 | raw_detach(so); | | 288 | raw_detach(so); |
289 | splx(s); | | 289 | splx(s); |
290 | } | | 290 | } |
291 | | | 291 | |
292 | static int | | 292 | static int |
293 | COMPATNAME(route_accept)(struct socket *so, struct sockaddr *nam) | | 293 | COMPATNAME(route_accept)(struct socket *so, struct sockaddr *nam) |
294 | { | | 294 | { |
295 | KASSERT(solocked(so)); | | 295 | KASSERT(solocked(so)); |
296 | | | 296 | |
297 | panic("route_accept"); | | 297 | panic("route_accept"); |
298 | | | 298 | |
299 | return EOPNOTSUPP; | | 299 | return EOPNOTSUPP; |
300 | } | | 300 | } |
301 | | | 301 | |
302 | static int | | 302 | static int |
303 | COMPATNAME(route_bind)(struct socket *so, struct sockaddr *nam, struct lwp *l) | | 303 | COMPATNAME(route_bind)(struct socket *so, struct sockaddr *nam, struct lwp *l) |
304 | { | | 304 | { |
305 | KASSERT(solocked(so)); | | 305 | KASSERT(solocked(so)); |
306 | | | 306 | |
307 | return EOPNOTSUPP; | | 307 | return EOPNOTSUPP; |
308 | } | | 308 | } |
309 | | | 309 | |
310 | static int | | 310 | static int |
311 | COMPATNAME(route_listen)(struct socket *so, struct lwp *l) | | 311 | COMPATNAME(route_listen)(struct socket *so, struct lwp *l) |
312 | { | | 312 | { |
313 | KASSERT(solocked(so)); | | 313 | KASSERT(solocked(so)); |
314 | | | 314 | |
315 | return EOPNOTSUPP; | | 315 | return EOPNOTSUPP; |
316 | } | | 316 | } |
317 | | | 317 | |
318 | static int | | 318 | static int |
319 | COMPATNAME(route_connect)(struct socket *so, struct sockaddr *nam, struct lwp *l) | | 319 | COMPATNAME(route_connect)(struct socket *so, struct sockaddr *nam, struct lwp *l) |
320 | { | | 320 | { |
321 | KASSERT(solocked(so)); | | 321 | KASSERT(solocked(so)); |
322 | | | 322 | |
323 | return EOPNOTSUPP; | | 323 | return EOPNOTSUPP; |
324 | } | | 324 | } |
325 | | | 325 | |
326 | static int | | 326 | static int |
327 | COMPATNAME(route_connect2)(struct socket *so, struct socket *so2) | | 327 | COMPATNAME(route_connect2)(struct socket *so, struct socket *so2) |
328 | { | | 328 | { |
329 | KASSERT(solocked(so)); | | 329 | KASSERT(solocked(so)); |
330 | | | 330 | |
331 | return EOPNOTSUPP; | | 331 | return EOPNOTSUPP; |
332 | } | | 332 | } |
333 | | | 333 | |
334 | static int | | 334 | static int |
335 | COMPATNAME(route_disconnect)(struct socket *so) | | 335 | COMPATNAME(route_disconnect)(struct socket *so) |
336 | { | | 336 | { |
337 | struct rawcb *rp = sotorawcb(so); | | 337 | struct rawcb *rp = sotorawcb(so); |
338 | int s; | | 338 | int s; |
339 | | | 339 | |
340 | KASSERT(solocked(so)); | | 340 | KASSERT(solocked(so)); |
341 | KASSERT(rp != NULL); | | 341 | KASSERT(rp != NULL); |
342 | | | 342 | |
343 | s = splsoftnet(); | | 343 | s = splsoftnet(); |
344 | soisdisconnected(so); | | 344 | soisdisconnected(so); |
345 | raw_disconnect(rp); | | 345 | raw_disconnect(rp); |
346 | splx(s); | | 346 | splx(s); |
347 | | | 347 | |
348 | return 0; | | 348 | return 0; |
349 | } | | 349 | } |
350 | | | 350 | |
351 | static int | | 351 | static int |
352 | COMPATNAME(route_shutdown)(struct socket *so) | | 352 | COMPATNAME(route_shutdown)(struct socket *so) |
353 | { | | 353 | { |
354 | int s; | | 354 | int s; |
355 | | | 355 | |
356 | KASSERT(solocked(so)); | | 356 | KASSERT(solocked(so)); |
357 | | | 357 | |
358 | /* | | 358 | /* |
359 | * Mark the connection as being incapable of further input. | | 359 | * Mark the connection as being incapable of further input. |
360 | */ | | 360 | */ |
361 | s = splsoftnet(); | | 361 | s = splsoftnet(); |
362 | socantsendmore(so); | | 362 | socantsendmore(so); |
363 | splx(s); | | 363 | splx(s); |
364 | return 0; | | 364 | return 0; |
365 | } | | 365 | } |
366 | | | 366 | |
367 | static int | | 367 | static int |
368 | COMPATNAME(route_abort)(struct socket *so) | | 368 | COMPATNAME(route_abort)(struct socket *so) |
369 | { | | 369 | { |
370 | KASSERT(solocked(so)); | | 370 | KASSERT(solocked(so)); |
371 | | | 371 | |
372 | panic("route_abort"); | | 372 | panic("route_abort"); |
373 | | | 373 | |
374 | return EOPNOTSUPP; | | 374 | return EOPNOTSUPP; |
375 | } | | 375 | } |
376 | | | 376 | |
377 | static int | | 377 | static int |
378 | COMPATNAME(route_ioctl)(struct socket *so, u_long cmd, void *nam, | | 378 | COMPATNAME(route_ioctl)(struct socket *so, u_long cmd, void *nam, |
379 | struct ifnet * ifp) | | 379 | struct ifnet * ifp) |
380 | { | | 380 | { |
381 | return EOPNOTSUPP; | | 381 | return EOPNOTSUPP; |
382 | } | | 382 | } |
383 | | | 383 | |
384 | static int | | 384 | static int |
385 | COMPATNAME(route_stat)(struct socket *so, struct stat *ub) | | 385 | COMPATNAME(route_stat)(struct socket *so, struct stat *ub) |
386 | { | | 386 | { |
387 | KASSERT(solocked(so)); | | 387 | KASSERT(solocked(so)); |
388 | | | 388 | |
389 | return 0; | | 389 | return 0; |
390 | } | | 390 | } |
391 | | | 391 | |
392 | static int | | 392 | static int |
393 | COMPATNAME(route_peeraddr)(struct socket *so, struct sockaddr *nam) | | 393 | COMPATNAME(route_peeraddr)(struct socket *so, struct sockaddr *nam) |
394 | { | | 394 | { |
395 | struct rawcb *rp = sotorawcb(so); | | 395 | struct rawcb *rp = sotorawcb(so); |
396 | | | 396 | |
397 | KASSERT(solocked(so)); | | 397 | KASSERT(solocked(so)); |
398 | KASSERT(rp != NULL); | | 398 | KASSERT(rp != NULL); |
399 | KASSERT(nam != NULL); | | 399 | KASSERT(nam != NULL); |
400 | | | 400 | |
401 | if (rp->rcb_faddr == NULL) | | 401 | if (rp->rcb_faddr == NULL) |
402 | return ENOTCONN; | | 402 | return ENOTCONN; |
403 | | | 403 | |
404 | raw_setpeeraddr(rp, nam); | | 404 | raw_setpeeraddr(rp, nam); |
405 | return 0; | | 405 | return 0; |
406 | } | | 406 | } |
407 | | | 407 | |
408 | static int | | 408 | static int |
409 | COMPATNAME(route_sockaddr)(struct socket *so, struct sockaddr *nam) | | 409 | COMPATNAME(route_sockaddr)(struct socket *so, struct sockaddr *nam) |
410 | { | | 410 | { |
411 | struct rawcb *rp = sotorawcb(so); | | 411 | struct rawcb *rp = sotorawcb(so); |
412 | | | 412 | |
413 | KASSERT(solocked(so)); | | 413 | KASSERT(solocked(so)); |
414 | KASSERT(rp != NULL); | | 414 | KASSERT(rp != NULL); |
415 | KASSERT(nam != NULL); | | 415 | KASSERT(nam != NULL); |
416 | | | 416 | |
417 | if (rp->rcb_faddr == NULL) | | 417 | if (rp->rcb_faddr == NULL) |
418 | return ENOTCONN; | | 418 | return ENOTCONN; |
419 | | | 419 | |
420 | raw_setsockaddr(rp, nam); | | 420 | raw_setsockaddr(rp, nam); |
421 | return 0; | | 421 | return 0; |
422 | } | | 422 | } |
423 | | | 423 | |
424 | static int | | 424 | static int |
425 | COMPATNAME(route_rcvd)(struct socket *so, int flags, struct lwp *l) | | 425 | COMPATNAME(route_rcvd)(struct socket *so, int flags, struct lwp *l) |
426 | { | | 426 | { |
427 | KASSERT(solocked(so)); | | 427 | KASSERT(solocked(so)); |
428 | | | 428 | |
429 | return EOPNOTSUPP; | | 429 | return EOPNOTSUPP; |
430 | } | | 430 | } |
431 | | | 431 | |
432 | static int | | 432 | static int |
433 | COMPATNAME(route_recvoob)(struct socket *so, struct mbuf *m, int flags) | | 433 | COMPATNAME(route_recvoob)(struct socket *so, struct mbuf *m, int flags) |
434 | { | | 434 | { |
435 | KASSERT(solocked(so)); | | 435 | KASSERT(solocked(so)); |
436 | | | 436 | |
437 | return EOPNOTSUPP; | | 437 | return EOPNOTSUPP; |
438 | } | | 438 | } |
439 | | | 439 | |
440 | static int | | 440 | static int |
441 | COMPATNAME(route_send)(struct socket *so, struct mbuf *m, | | 441 | COMPATNAME(route_send)(struct socket *so, struct mbuf *m, |
442 | struct sockaddr *nam, struct mbuf *control, struct lwp *l) | | 442 | struct sockaddr *nam, struct mbuf *control, struct lwp *l) |
443 | { | | 443 | { |
444 | int error = 0; | | 444 | int error = 0; |
445 | int s; | | 445 | int s; |
446 | | | 446 | |
447 | KASSERT(solocked(so)); | | 447 | KASSERT(solocked(so)); |
448 | KASSERT(so->so_proto == &COMPATNAME(route_protosw)[0]); | | 448 | KASSERT(so->so_proto == &COMPATNAME(route_protosw)[0]); |
449 | | | 449 | |
450 | s = splsoftnet(); | | 450 | s = splsoftnet(); |
451 | error = raw_send(so, m, nam, control, l, &COMPATNAME(route_output)); | | 451 | error = raw_send(so, m, nam, control, l, &COMPATNAME(route_output)); |
452 | splx(s); | | 452 | splx(s); |
453 | | | 453 | |
454 | return error; | | 454 | return error; |
455 | } | | 455 | } |
456 | | | 456 | |
457 | static int | | 457 | static int |
458 | COMPATNAME(route_sendoob)(struct socket *so, struct mbuf *m, | | 458 | COMPATNAME(route_sendoob)(struct socket *so, struct mbuf *m, |
459 | struct mbuf *control) | | 459 | struct mbuf *control) |
460 | { | | 460 | { |
461 | KASSERT(solocked(so)); | | 461 | KASSERT(solocked(so)); |
462 | | | 462 | |
463 | m_freem(m); | | 463 | m_freem(m); |
464 | m_freem(control); | | 464 | m_freem(control); |
465 | | | 465 | |
466 | return EOPNOTSUPP; | | 466 | return EOPNOTSUPP; |
467 | } | | 467 | } |
468 | static int | | 468 | static int |
469 | COMPATNAME(route_purgeif)(struct socket *so, struct ifnet *ifp) | | 469 | COMPATNAME(route_purgeif)(struct socket *so, struct ifnet *ifp) |
470 | { | | 470 | { |
471 | | | 471 | |
472 | panic("route_purgeif"); | | 472 | panic("route_purgeif"); |
473 | | | 473 | |
474 | return EOPNOTSUPP; | | 474 | return EOPNOTSUPP; |
475 | } | | 475 | } |
476 | | | 476 | |
477 | #ifdef INET | | 477 | #ifdef INET |
478 | static int | | 478 | static int |
479 | route_get_sdl_index(struct rt_addrinfo *info, int *sdl_index) | | 479 | route_get_sdl_index(struct rt_addrinfo *info, int *sdl_index) |
480 | { | | 480 | { |
481 | struct rtentry *nrt; | | 481 | struct rtentry *nrt; |
482 | int error; | | 482 | int error; |
483 | | | 483 | |
484 | error = rtrequest1(RTM_GET, info, &nrt); | | 484 | error = rtrequest1(RTM_GET, info, &nrt); |
485 | if (error != 0) | | 485 | if (error != 0) |
486 | return error; | | 486 | return error; |
487 | /* | | 487 | /* |
488 | * nrt->rt_ifp->if_index may not be correct | | 488 | * nrt->rt_ifp->if_index may not be correct |
489 | * due to changing to ifplo0. | | 489 | * due to changing to ifplo0. |
490 | */ | | 490 | */ |
491 | *sdl_index = satosdl(nrt->rt_gateway)->sdl_index; | | 491 | *sdl_index = satosdl(nrt->rt_gateway)->sdl_index; |
492 | rt_unref(nrt); | | 492 | rt_unref(nrt); |
493 | | | 493 | |
494 | return 0; | | 494 | return 0; |
495 | } | | 495 | } |
496 | #endif /* INET */ | | 496 | #endif /* INET */ |
497 | | | 497 | |
498 | static void | | 498 | static void |
499 | route_get_sdl(const struct ifnet *ifp, const struct sockaddr *dst, | | 499 | route_get_sdl(const struct ifnet *ifp, const struct sockaddr *dst, |
500 | struct sockaddr_dl *sdl, int *flags) | | 500 | struct sockaddr_dl *sdl, int *flags) |
501 | { | | 501 | { |
502 | struct llentry *la; | | 502 | struct llentry *la; |
503 | | | 503 | |
504 | KASSERT(ifp != NULL); | | 504 | KASSERT(ifp != NULL); |
505 | | | 505 | |
506 | IF_AFDATA_RLOCK(ifp); | | 506 | IF_AFDATA_RLOCK(ifp); |
507 | switch (dst->sa_family) { | | 507 | switch (dst->sa_family) { |
508 | case AF_INET: | | 508 | case AF_INET: |
509 | la = lla_lookup(LLTABLE(ifp), 0, dst); | | 509 | la = lla_lookup(LLTABLE(ifp), 0, dst); |
510 | break; | | 510 | break; |
511 | case AF_INET6: | | 511 | case AF_INET6: |
512 | la = lla_lookup(LLTABLE6(ifp), 0, dst); | | 512 | la = lla_lookup(LLTABLE6(ifp), 0, dst); |
513 | break; | | 513 | break; |
514 | default: | | 514 | default: |
515 | la = NULL; | | 515 | la = NULL; |
516 | KASSERTMSG(0, "Invalid AF=%d\n", dst->sa_family); | | 516 | KASSERTMSG(0, "Invalid AF=%d\n", dst->sa_family); |
517 | break; | | 517 | break; |
518 | } | | 518 | } |
519 | IF_AFDATA_RUNLOCK(ifp); | | 519 | IF_AFDATA_RUNLOCK(ifp); |
520 | | | 520 | |
521 | void *a = (LLE_IS_VALID(la) && (la->la_flags & LLE_VALID) == LLE_VALID) | | 521 | void *a = (LLE_IS_VALID(la) && (la->la_flags & LLE_VALID) == LLE_VALID) |
522 | ? &la->ll_addr : NULL; | | 522 | ? &la->ll_addr : NULL; |
523 | | | 523 | |
524 | a = sockaddr_dl_init(sdl, sizeof(*sdl), ifp->if_index, ifp->if_type, | | 524 | a = sockaddr_dl_init(sdl, sizeof(*sdl), ifp->if_index, ifp->if_type, |
525 | NULL, 0, a, ifp->if_addrlen); | | 525 | NULL, 0, a, ifp->if_addrlen); |
526 | KASSERT(a != NULL); | | 526 | KASSERT(a != NULL); |
527 | | | 527 | |
528 | if (la != NULL) { | | 528 | if (la != NULL) { |
529 | *flags = la->la_flags; | | 529 | *flags = la->la_flags; |
530 | LLE_RUNLOCK(la); | | 530 | LLE_RUNLOCK(la); |
531 | } | | 531 | } |
532 | } | | 532 | } |
533 | | | 533 | |
534 | static int | | 534 | static int |
535 | route_output_report(struct rtentry *rt, struct rt_addrinfo *info, | | 535 | route_output_report(struct rtentry *rt, struct rt_addrinfo *info, |
536 | struct rt_xmsghdr *rtm, struct rt_xmsghdr **new_rtm) | | 536 | struct rt_xmsghdr *rtm, struct rt_xmsghdr **new_rtm) |
537 | { | | 537 | { |
538 | int len; | | 538 | int len; |
539 | struct ifnet *ifp; | | | |
540 | | | 539 | |
541 | if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0) | | 540 | if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { |
542 | ; | | | |
543 | else if ((ifp = rt->rt_ifp) != NULL) { | | | |
544 | const struct ifaddr *rtifa; | | 541 | const struct ifaddr *rtifa; |
| | | 542 | const struct ifnet *ifp = rt->rt_ifp; |
| | | 543 | |
545 | info->rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; | | 544 | info->rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; |
546 | /* rtifa used to be simply rt->rt_ifa. | | 545 | /* rtifa used to be simply rt->rt_ifa. |
547 | * If rt->rt_ifa != NULL, then | | 546 | * If rt->rt_ifa != NULL, then |
548 | * rt_get_ifa() != NULL. So this | | 547 | * rt_get_ifa() != NULL. So this |
549 | * ought to still be safe. --dyoung | | 548 | * ought to still be safe. --dyoung |
550 | */ | | 549 | */ |
551 | rtifa = rt_get_ifa(rt); | | 550 | rtifa = rt_get_ifa(rt); |
552 | info->rti_info[RTAX_IFA] = rtifa->ifa_addr; | | 551 | info->rti_info[RTAX_IFA] = rtifa->ifa_addr; |
553 | #ifdef RTSOCK_DEBUG | | 552 | #ifdef RTSOCK_DEBUG |
554 | if (info->rti_info[RTAX_IFA]->sa_family == AF_INET) { | | 553 | if (info->rti_info[RTAX_IFA]->sa_family == AF_INET) { |
555 | char ibuf[INET_ADDRSTRLEN]; | | 554 | char ibuf[INET_ADDRSTRLEN]; |
556 | char abuf[INET_ADDRSTRLEN]; | | 555 | char abuf[INET_ADDRSTRLEN]; |
557 | printf("%s: copying out RTAX_IFA %s " | | 556 | printf("%s: copying out RTAX_IFA %s " |
558 | "for info->rti_info[RTAX_DST] %s " | | 557 | "for info->rti_info[RTAX_DST] %s " |
559 | "ifa_getifa %p ifa_seqno %p\n", | | 558 | "ifa_getifa %p ifa_seqno %p\n", |
560 | __func__, | | 559 | __func__, |
561 | RT_IN_PRINT(info, ibuf, RTAX_IFA), | | 560 | RT_IN_PRINT(info, ibuf, RTAX_IFA), |
562 | RT_IN_PRINT(info, abuf, RTAX_DST), | | 561 | RT_IN_PRINT(info, abuf, RTAX_DST), |
563 | (void *)rtifa->ifa_getifa, | | 562 | (void *)rtifa->ifa_getifa, |
564 | rtifa->ifa_seqno); | | 563 | rtifa->ifa_seqno); |
565 | } | | 564 | } |
566 | #endif /* RTSOCK_DEBUG */ | | 565 | #endif /* RTSOCK_DEBUG */ |
567 | if (ifp->if_flags & IFF_POINTOPOINT) | | 566 | if (ifp->if_flags & IFF_POINTOPOINT) |
568 | info->rti_info[RTAX_BRD] = rtifa->ifa_dstaddr; | | 567 | info->rti_info[RTAX_BRD] = rtifa->ifa_dstaddr; |
569 | else | | 568 | else |
570 | info->rti_info[RTAX_BRD] = NULL; | | 569 | info->rti_info[RTAX_BRD] = NULL; |
571 | rtm->rtm_index = ifp->if_index; | | 570 | rtm->rtm_index = ifp->if_index; |
572 | } else { | | | |
573 | info->rti_info[RTAX_IFP] = NULL; | | | |
574 | info->rti_info[RTAX_IFA] = NULL; | | | |
575 | } | | 571 | } |
576 | (void)rt_msg2(rtm->rtm_type, info, NULL, NULL, &len); | | 572 | (void)rt_msg2(rtm->rtm_type, info, NULL, NULL, &len); |
577 | if (len > rtm->rtm_msglen) { | | 573 | if (len > rtm->rtm_msglen) { |
578 | struct rt_xmsghdr *old_rtm = rtm; | | 574 | struct rt_xmsghdr *old_rtm = rtm; |
579 | R_Malloc(*new_rtm, struct rt_xmsghdr *, len); | | 575 | R_Malloc(*new_rtm, struct rt_xmsghdr *, len); |
580 | if (*new_rtm == NULL) | | 576 | if (*new_rtm == NULL) |
581 | return ENOBUFS; | | 577 | return ENOBUFS; |
582 | (void)memcpy(*new_rtm, old_rtm, old_rtm->rtm_msglen); | | 578 | (void)memcpy(*new_rtm, old_rtm, old_rtm->rtm_msglen); |
583 | rtm = *new_rtm; | | 579 | rtm = *new_rtm; |
584 | } | | 580 | } |
585 | (void)rt_msg2(rtm->rtm_type, info, rtm, NULL, 0); | | 581 | (void)rt_msg2(rtm->rtm_type, info, rtm, NULL, 0); |
586 | rtm->rtm_flags = rt->rt_flags; | | 582 | rtm->rtm_flags = rt->rt_flags; |
587 | rtm_setmetrics(rt, rtm); | | 583 | rtm_setmetrics(rt, rtm); |
588 | rtm->rtm_addrs = info->rti_addrs; | | 584 | rtm->rtm_addrs = info->rti_addrs; |
589 | | | 585 | |
590 | return 0; | | 586 | return 0; |
591 | } | | 587 | } |
592 | | | 588 | |
593 | static struct ifaddr * | | 589 | static struct ifaddr * |
594 | route_output_get_ifa(const struct rt_addrinfo info, const struct rtentry *rt, | | 590 | route_output_get_ifa(const struct rt_addrinfo info, const struct rtentry *rt, |
595 | struct ifnet **ifp, struct psref *psref) | | 591 | struct ifnet **ifp, struct psref *psref) |
596 | { | | 592 | { |
597 | struct ifaddr *ifa = NULL; | | 593 | struct ifaddr *ifa = NULL; |
598 | | | 594 | |
599 | *ifp = NULL; | | 595 | *ifp = NULL; |
600 | if (info.rti_info[RTAX_IFP] != NULL) { | | 596 | if (info.rti_info[RTAX_IFP] != NULL) { |
601 | ifa = ifa_ifwithnet_psref(info.rti_info[RTAX_IFP], psref); | | 597 | ifa = ifa_ifwithnet_psref(info.rti_info[RTAX_IFP], psref); |
602 | if (ifa == NULL) | | 598 | if (ifa == NULL) |
603 | goto next; | | 599 | goto next; |
604 | *ifp = ifa->ifa_ifp; | | 600 | *ifp = ifa->ifa_ifp; |
605 | if (info.rti_info[RTAX_IFA] == NULL && | | 601 | if (info.rti_info[RTAX_IFA] == NULL && |
606 | info.rti_info[RTAX_GATEWAY] == NULL) | | 602 | info.rti_info[RTAX_GATEWAY] == NULL) |
607 | goto next; | | 603 | goto next; |
608 | if (info.rti_info[RTAX_IFA] == NULL) { | | 604 | if (info.rti_info[RTAX_IFA] == NULL) { |
609 | /* route change <dst> <gw> -ifp <if> */ | | 605 | /* route change <dst> <gw> -ifp <if> */ |
610 | ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_GATEWAY], | | 606 | ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_GATEWAY], |
611 | *ifp, psref); | | 607 | *ifp, psref); |
612 | } else { | | 608 | } else { |
613 | /* route change <dst> -ifp <if> -ifa <addr> */ | | 609 | /* route change <dst> -ifp <if> -ifa <addr> */ |
614 | ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref); | | 610 | ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref); |
615 | if (ifa != NULL) | | 611 | if (ifa != NULL) |
616 | goto out; | | 612 | goto out; |
617 | ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_IFA], | | 613 | ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_IFA], |
618 | *ifp, psref); | | 614 | *ifp, psref); |
619 | } | | 615 | } |
620 | goto out; | | 616 | goto out; |
621 | } | | 617 | } |
622 | next: | | 618 | next: |
623 | if (info.rti_info[RTAX_IFA] != NULL) { | | 619 | if (info.rti_info[RTAX_IFA] != NULL) { |
624 | /* route change <dst> <gw> -ifa <addr> */ | | 620 | /* route change <dst> <gw> -ifa <addr> */ |
625 | ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref); | | 621 | ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref); |
626 | if (ifa != NULL) | | 622 | if (ifa != NULL) |
627 | goto out; | | 623 | goto out; |
628 | } | | 624 | } |
629 | if (info.rti_info[RTAX_GATEWAY] != NULL) { | | 625 | if (info.rti_info[RTAX_GATEWAY] != NULL) { |
630 | /* route change <dst> <gw> */ | | 626 | /* route change <dst> <gw> */ |
631 | ifa = ifa_ifwithroute_psref(rt->rt_flags, rt_getkey(rt), | | 627 | ifa = ifa_ifwithroute_psref(rt->rt_flags, rt_getkey(rt), |
632 | info.rti_info[RTAX_GATEWAY], psref); | | 628 | info.rti_info[RTAX_GATEWAY], psref); |
633 | } | | 629 | } |
634 | out: | | 630 | out: |
635 | if (ifa != NULL && *ifp == NULL) | | 631 | if (ifa != NULL && *ifp == NULL) |
636 | *ifp = ifa->ifa_ifp; | | 632 | *ifp = ifa->ifa_ifp; |
637 | return ifa; | | 633 | return ifa; |
638 | } | | 634 | } |
639 | | | 635 | |
640 | static int | | 636 | static int |
641 | route_output_change(struct rtentry *rt, struct rt_addrinfo *info, | | 637 | route_output_change(struct rtentry *rt, struct rt_addrinfo *info, |
642 | struct rt_xmsghdr *rtm) | | 638 | struct rt_xmsghdr *rtm) |
643 | { | | 639 | { |
644 | int error = 0; | | 640 | int error = 0; |
645 | struct ifnet *ifp = NULL, *new_ifp; | | 641 | struct ifnet *ifp = NULL, *new_ifp; |
646 | struct ifaddr *ifa = NULL, *new_ifa; | | 642 | struct ifaddr *ifa = NULL, *new_ifa; |
647 | struct psref psref_ifa, psref_new_ifa, psref_ifp; | | 643 | struct psref psref_ifa, psref_new_ifa, psref_ifp; |
648 | bool newgw; | | 644 | bool newgw; |
649 | | | 645 | |
650 | /* | | 646 | /* |
651 | * New gateway could require new ifaddr, ifp; | | 647 | * New gateway could require new ifaddr, ifp; |
652 | * flags may also be different; ifp may be specified | | 648 | * flags may also be different; ifp may be specified |
653 | * by ll sockaddr when protocol address is ambiguous | | 649 | * by ll sockaddr when protocol address is ambiguous |
654 | */ | | 650 | */ |
655 | newgw = info->rti_info[RTAX_GATEWAY] != NULL && | | 651 | newgw = info->rti_info[RTAX_GATEWAY] != NULL && |
656 | sockaddr_cmp(info->rti_info[RTAX_GATEWAY], rt->rt_gateway) != 0; | | 652 | sockaddr_cmp(info->rti_info[RTAX_GATEWAY], rt->rt_gateway) != 0; |
657 | | | 653 | |
658 | if (newgw || info->rti_info[RTAX_IFP] != NULL || | | 654 | if (newgw || info->rti_info[RTAX_IFP] != NULL || |
659 | info->rti_info[RTAX_IFA] != NULL) { | | 655 | info->rti_info[RTAX_IFA] != NULL) { |
660 | ifp = rt_getifp(info, &psref_ifp); | | 656 | ifp = rt_getifp(info, &psref_ifp); |
661 | ifa = rt_getifa(info, &psref_ifa); | | 657 | ifa = rt_getifa(info, &psref_ifa); |
662 | if (ifa == NULL) { | | 658 | if (ifa == NULL) { |
663 | error = ENETUNREACH; | | 659 | error = ENETUNREACH; |
664 | goto out; | | 660 | goto out; |
665 | } | | 661 | } |
666 | } | | 662 | } |
667 | if (newgw) { | | 663 | if (newgw) { |
668 | error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY]); | | 664 | error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY]); |
669 | if (error != 0) | | 665 | if (error != 0) |
670 | goto out; | | 666 | goto out; |
671 | } | | 667 | } |
672 | if (info->rti_info[RTAX_TAG]) { | | 668 | if (info->rti_info[RTAX_TAG]) { |
673 | const struct sockaddr *tag; | | 669 | const struct sockaddr *tag; |
674 | tag = rt_settag(rt, info->rti_info[RTAX_TAG]); | | 670 | tag = rt_settag(rt, info->rti_info[RTAX_TAG]); |
675 | if (tag == NULL) { | | 671 | if (tag == NULL) { |
676 | error = ENOBUFS; | | 672 | error = ENOBUFS; |
677 | goto out; | | 673 | goto out; |
678 | } | | 674 | } |
679 | } | | 675 | } |
680 | /* | | 676 | /* |
681 | * New gateway could require new ifaddr, ifp; | | 677 | * New gateway could require new ifaddr, ifp; |
682 | * flags may also be different; ifp may be specified | | 678 | * flags may also be different; ifp may be specified |
683 | * by ll sockaddr when protocol address is ambiguous | | 679 | * by ll sockaddr when protocol address is ambiguous |
684 | */ | | 680 | */ |
685 | new_ifa = route_output_get_ifa(*info, rt, &new_ifp, &psref_new_ifa); | | 681 | new_ifa = route_output_get_ifa(*info, rt, &new_ifp, &psref_new_ifa); |
686 | if (new_ifa != NULL) { | | 682 | if (new_ifa != NULL) { |
687 | ifa_release(ifa, &psref_ifa); | | 683 | ifa_release(ifa, &psref_ifa); |
688 | ifa = new_ifa; | | 684 | ifa = new_ifa; |
689 | } | | 685 | } |
690 | if (ifa) { | | 686 | if (ifa) { |
691 | struct ifaddr *oifa = rt->rt_ifa; | | 687 | struct ifaddr *oifa = rt->rt_ifa; |
692 | if (oifa != ifa && !ifa_is_destroying(ifa) && | | 688 | if (oifa != ifa && !ifa_is_destroying(ifa) && |
693 | new_ifp != NULL && !if_is_deactivated(new_ifp)) { | | 689 | new_ifp != NULL && !if_is_deactivated(new_ifp)) { |
694 | if (oifa && oifa->ifa_rtrequest) | | 690 | if (oifa && oifa->ifa_rtrequest) |
695 | oifa->ifa_rtrequest(RTM_DELETE, rt, info); | | 691 | oifa->ifa_rtrequest(RTM_DELETE, rt, info); |
696 | rt_replace_ifa(rt, ifa); | | 692 | rt_replace_ifa(rt, ifa); |
697 | rt->rt_ifp = new_ifp; | | 693 | rt->rt_ifp = new_ifp; |
698 | } | | 694 | } |
699 | if (new_ifa == NULL) | | 695 | if (new_ifa == NULL) |
700 | ifa_release(ifa, &psref_ifa); | | 696 | ifa_release(ifa, &psref_ifa); |
701 | } | | 697 | } |
702 | ifa_release(new_ifa, &psref_new_ifa); | | 698 | ifa_release(new_ifa, &psref_new_ifa); |
703 | if (new_ifp && rt->rt_ifp != new_ifp && !if_is_deactivated(new_ifp)) | | 699 | if (new_ifp && rt->rt_ifp != new_ifp && !if_is_deactivated(new_ifp)) |
704 | rt->rt_ifp = new_ifp; | | 700 | rt->rt_ifp = new_ifp; |
705 | rt_setmetrics(rtm->rtm_inits, rtm, rt); | | 701 | rt_setmetrics(rtm->rtm_inits, rtm, rt); |
706 | if (rt->rt_flags != info->rti_flags) { | | 702 | if (rt->rt_flags != info->rti_flags) { |
707 | rt->rt_flags = (info->rti_flags & ~PRESERVED_RTF) | | | 703 | rt->rt_flags = (info->rti_flags & ~PRESERVED_RTF) | |
708 | (rt->rt_flags & PRESERVED_RTF); | | 704 | (rt->rt_flags & PRESERVED_RTF); |
709 | } | | 705 | } |
710 | if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) | | 706 | if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest) |
711 | rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info); | | 707 | rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info); |
712 | out: | | 708 | out: |
713 | if_put(ifp, &psref_ifp); | | 709 | if_put(ifp, &psref_ifp); |
714 | | | 710 | |
715 | return error; | | 711 | return error; |
716 | } | | 712 | } |
717 | | | 713 | |
718 | /*ARGSUSED*/ | | 714 | /*ARGSUSED*/ |
719 | int | | 715 | int |
720 | COMPATNAME(route_output)(struct mbuf *m, struct socket *so) | | 716 | COMPATNAME(route_output)(struct mbuf *m, struct socket *so) |
721 | { | | 717 | { |
722 | struct sockproto proto = { .sp_family = PF_XROUTE, }; | | 718 | struct sockproto proto = { .sp_family = PF_XROUTE, }; |
723 | struct rt_xmsghdr *rtm = NULL; | | 719 | struct rt_xmsghdr *rtm = NULL; |
724 | struct rt_xmsghdr *old_rtm = NULL, *new_rtm = NULL; | | 720 | struct rt_xmsghdr *old_rtm = NULL, *new_rtm = NULL; |
725 | struct rtentry *rt = NULL; | | 721 | struct rtentry *rt = NULL; |
726 | struct rtentry *saved_nrt = NULL; | | 722 | struct rtentry *saved_nrt = NULL; |
727 | struct rt_addrinfo info; | | 723 | struct rt_addrinfo info; |
728 | int len, error = 0; | | 724 | int len, error = 0; |
729 | sa_family_t family; | | 725 | sa_family_t family; |
730 | struct sockaddr_dl sdl; | | 726 | struct sockaddr_dl sdl; |
731 | int bound = curlwp_bind(); | | 727 | int bound = curlwp_bind(); |
732 | bool do_rt_free = false; | | 728 | bool do_rt_free = false; |
733 | | | 729 | |
734 | #define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0) | | 730 | #define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0) |
735 | if (m == NULL || ((m->m_len < sizeof(int32_t)) && | | 731 | if (m == NULL || ((m->m_len < sizeof(int32_t)) && |
736 | (m = m_pullup(m, sizeof(int32_t))) == NULL)) { | | 732 | (m = m_pullup(m, sizeof(int32_t))) == NULL)) { |
737 | error = ENOBUFS; | | 733 | error = ENOBUFS; |
738 | goto out; | | 734 | goto out; |
739 | } | | 735 | } |
740 | if ((m->m_flags & M_PKTHDR) == 0) | | 736 | if ((m->m_flags & M_PKTHDR) == 0) |
741 | panic("%s", __func__); | | 737 | panic("%s", __func__); |
742 | len = m->m_pkthdr.len; | | 738 | len = m->m_pkthdr.len; |
743 | if (len < sizeof(*rtm) || | | 739 | if (len < sizeof(*rtm) || |
744 | len != mtod(m, struct rt_xmsghdr *)->rtm_msglen) { | | 740 | len != mtod(m, struct rt_xmsghdr *)->rtm_msglen) { |
745 | info.rti_info[RTAX_DST] = NULL; | | 741 | info.rti_info[RTAX_DST] = NULL; |
746 | senderr(EINVAL); | | 742 | senderr(EINVAL); |
747 | } | | 743 | } |
748 | R_Malloc(rtm, struct rt_xmsghdr *, len); | | 744 | R_Malloc(rtm, struct rt_xmsghdr *, len); |
749 | if (rtm == NULL) { | | 745 | if (rtm == NULL) { |
750 | info.rti_info[RTAX_DST] = NULL; | | 746 | info.rti_info[RTAX_DST] = NULL; |
751 | senderr(ENOBUFS); | | 747 | senderr(ENOBUFS); |
752 | } | | 748 | } |
753 | m_copydata(m, 0, len, rtm); | | 749 | m_copydata(m, 0, len, rtm); |
754 | if (rtm->rtm_version != RTM_XVERSION) { | | 750 | if (rtm->rtm_version != RTM_XVERSION) { |
755 | info.rti_info[RTAX_DST] = NULL; | | 751 | info.rti_info[RTAX_DST] = NULL; |
756 | senderr(EPROTONOSUPPORT); | | 752 | senderr(EPROTONOSUPPORT); |
757 | } | | 753 | } |
758 | rtm->rtm_pid = curproc->p_pid; | | 754 | rtm->rtm_pid = curproc->p_pid; |
759 | memset(&info, 0, sizeof(info)); | | 755 | memset(&info, 0, sizeof(info)); |
760 | info.rti_addrs = rtm->rtm_addrs; | | 756 | info.rti_addrs = rtm->rtm_addrs; |
761 | if (rt_xaddrs(rtm->rtm_type, (const char *)(rtm + 1), len + (char *)rtm, | | 757 | if (rt_xaddrs(rtm->rtm_type, (const char *)(rtm + 1), len + (char *)rtm, |
762 | &info)) { | | 758 | &info)) { |
763 | senderr(EINVAL); | | 759 | senderr(EINVAL); |
764 | } | | 760 | } |
765 | info.rti_flags = rtm->rtm_flags; | | 761 | info.rti_flags = rtm->rtm_flags; |
766 | #ifdef RTSOCK_DEBUG | | 762 | #ifdef RTSOCK_DEBUG |
767 | if (info.rti_info[RTAX_DST]->sa_family == AF_INET) { | | 763 | if (info.rti_info[RTAX_DST]->sa_family == AF_INET) { |
768 | char abuf[INET_ADDRSTRLEN]; | | 764 | char abuf[INET_ADDRSTRLEN]; |
769 | printf("%s: extracted info.rti_info[RTAX_DST] %s\n", __func__, | | 765 | printf("%s: extracted info.rti_info[RTAX_DST] %s\n", __func__, |
770 | RT_IN_PRINT(&info, abuf, RTAX_DST)); | | 766 | RT_IN_PRINT(&info, abuf, RTAX_DST)); |
771 | } | | 767 | } |
772 | #endif /* RTSOCK_DEBUG */ | | 768 | #endif /* RTSOCK_DEBUG */ |
773 | if (info.rti_info[RTAX_DST] == NULL || | | 769 | if (info.rti_info[RTAX_DST] == NULL || |
774 | (info.rti_info[RTAX_DST]->sa_family >= AF_MAX)) { | | 770 | (info.rti_info[RTAX_DST]->sa_family >= AF_MAX)) { |
775 | senderr(EINVAL); | | 771 | senderr(EINVAL); |
776 | } | | 772 | } |
777 | if (info.rti_info[RTAX_GATEWAY] != NULL && | | 773 | if (info.rti_info[RTAX_GATEWAY] != NULL && |
778 | (info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) { | | 774 | (info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX)) { |
779 | senderr(EINVAL); | | 775 | senderr(EINVAL); |
780 | } | | 776 | } |
781 | | | 777 | |
782 | /* | | 778 | /* |
783 | * Verify that the caller has the appropriate privilege; RTM_GET | | 779 | * Verify that the caller has the appropriate privilege; RTM_GET |
784 | * is the only operation the non-superuser is allowed. | | 780 | * is the only operation the non-superuser is allowed. |
785 | */ | | 781 | */ |
786 | if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_ROUTE, | | 782 | if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_ROUTE, |
787 | 0, rtm, NULL, NULL) != 0) | | 783 | 0, rtm, NULL, NULL) != 0) |
788 | senderr(EACCES); | | 784 | senderr(EACCES); |
789 | | | 785 | |
790 | switch (rtm->rtm_type) { | | 786 | switch (rtm->rtm_type) { |
791 | | | 787 | |
792 | case RTM_ADD: | | 788 | case RTM_ADD: |
793 | if (info.rti_info[RTAX_GATEWAY] == NULL) { | | 789 | if (info.rti_info[RTAX_GATEWAY] == NULL) { |
794 | senderr(EINVAL); | | 790 | senderr(EINVAL); |
795 | } | | 791 | } |
796 | #ifdef INET | | 792 | #ifdef INET |
797 | /* support for new ARP code with keeping backcompat */ | | 793 | /* support for new ARP code with keeping backcompat */ |
798 | if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) { | | 794 | if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) { |
799 | const struct sockaddr_dl *sdlp = | | 795 | const struct sockaddr_dl *sdlp = |
800 | satocsdl(info.rti_info[RTAX_GATEWAY]); | | 796 | satocsdl(info.rti_info[RTAX_GATEWAY]); |
801 | | | 797 | |
802 | /* Allow routing requests by interface index */ | | 798 | /* Allow routing requests by interface index */ |
803 | if (sdlp->sdl_nlen == 0 && sdlp->sdl_alen == 0 | | 799 | if (sdlp->sdl_nlen == 0 && sdlp->sdl_alen == 0 |
804 | && sdlp->sdl_slen == 0) | | 800 | && sdlp->sdl_slen == 0) |
805 | goto fallback; | | 801 | goto fallback; |
806 | /* | | 802 | /* |
807 | * Old arp binaries don't set the sdl_index | | 803 | * Old arp binaries don't set the sdl_index |
808 | * so we have to complement it. | | 804 | * so we have to complement it. |
809 | */ | | 805 | */ |
810 | int sdl_index = sdlp->sdl_index; | | 806 | int sdl_index = sdlp->sdl_index; |
811 | if (sdl_index == 0) { | | 807 | if (sdl_index == 0) { |
812 | error = route_get_sdl_index(&info, &sdl_index); | | 808 | error = route_get_sdl_index(&info, &sdl_index); |
813 | if (error != 0) | | 809 | if (error != 0) |
814 | goto fallback; | | 810 | goto fallback; |
815 | } else if ( | | 811 | } else if ( |
816 | info.rti_info[RTAX_DST]->sa_family == AF_INET) { | | 812 | info.rti_info[RTAX_DST]->sa_family == AF_INET) { |
817 | /* | | 813 | /* |
818 | * XXX workaround for SIN_PROXY case; proxy arp | | 814 | * XXX workaround for SIN_PROXY case; proxy arp |
819 | * entry should be in an interface that has | | 815 | * entry should be in an interface that has |
820 | * a network route including the destination, | | 816 | * a network route including the destination, |
821 | * not a local (link) route that may not be a | | 817 | * not a local (link) route that may not be a |
822 | * desired place, for example a tap. | | 818 | * desired place, for example a tap. |
823 | */ | | 819 | */ |
824 | const struct sockaddr_inarp *sina = | | 820 | const struct sockaddr_inarp *sina = |
825 | (const struct sockaddr_inarp *) | | 821 | (const struct sockaddr_inarp *) |
826 | info.rti_info[RTAX_DST]; | | 822 | info.rti_info[RTAX_DST]; |
827 | if (sina->sin_other & SIN_PROXY) { | | 823 | if (sina->sin_other & SIN_PROXY) { |
828 | error = route_get_sdl_index(&info, | | 824 | error = route_get_sdl_index(&info, |
829 | &sdl_index); | | 825 | &sdl_index); |
830 | if (error != 0) | | 826 | if (error != 0) |
831 | goto fallback; | | 827 | goto fallback; |
832 | } | | 828 | } |
833 | } | | 829 | } |
834 | error = lla_rt_output(rtm->rtm_type, rtm->rtm_flags, | | 830 | error = lla_rt_output(rtm->rtm_type, rtm->rtm_flags, |
835 | rtm->rtm_rmx.rmx_expire, &info, sdl_index); | | 831 | rtm->rtm_rmx.rmx_expire, &info, sdl_index); |
836 | break; | | 832 | break; |
837 | } | | 833 | } |
838 | fallback: | | 834 | fallback: |
839 | #endif /* INET */ | | 835 | #endif /* INET */ |
840 | error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); | | 836 | error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); |
841 | if (error == 0) { | | 837 | if (error == 0) { |
842 | rt_setmetrics(rtm->rtm_inits, rtm, saved_nrt); | | 838 | rt_setmetrics(rtm->rtm_inits, rtm, saved_nrt); |
843 | rt_unref(saved_nrt); | | 839 | rt_unref(saved_nrt); |
844 | } | | 840 | } |
845 | break; | | 841 | break; |
846 | | | 842 | |
847 | case RTM_DELETE: | | 843 | case RTM_DELETE: |
848 | #ifdef INET | | 844 | #ifdef INET |
849 | /* support for new ARP code */ | | 845 | /* support for new ARP code */ |
850 | if (info.rti_info[RTAX_GATEWAY] && | | 846 | if (info.rti_info[RTAX_GATEWAY] && |
851 | (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) && | | 847 | (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) && |
852 | (rtm->rtm_flags & RTF_LLDATA) != 0) { | | 848 | (rtm->rtm_flags & RTF_LLDATA) != 0) { |
853 | error = lla_rt_output(rtm->rtm_type, rtm->rtm_flags, | | 849 | error = lla_rt_output(rtm->rtm_type, rtm->rtm_flags, |
854 | rtm->rtm_rmx.rmx_expire, &info, 0); | | 850 | rtm->rtm_rmx.rmx_expire, &info, 0); |
855 | break; | | 851 | break; |
856 | } | | 852 | } |
857 | #endif /* INET */ | | 853 | #endif /* INET */ |
858 | error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); | | 854 | error = rtrequest1(rtm->rtm_type, &info, &saved_nrt); |
859 | if (error != 0) | | 855 | if (error != 0) |
860 | break; | | 856 | break; |
861 | | | 857 | |
862 | rt = saved_nrt; | | 858 | rt = saved_nrt; |
863 | do_rt_free = true; | | 859 | do_rt_free = true; |
864 | info.rti_info[RTAX_DST] = rt_getkey(rt); | | 860 | info.rti_info[RTAX_DST] = rt_getkey(rt); |
865 | info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; | | 861 | info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; |
866 | info.rti_info[RTAX_NETMASK] = rt_mask(rt); | | 862 | info.rti_info[RTAX_NETMASK] = rt_mask(rt); |
867 | info.rti_info[RTAX_TAG] = rt_gettag(rt); | | 863 | info.rti_info[RTAX_TAG] = rt_gettag(rt); |
868 | error = route_output_report(rt, &info, rtm, &new_rtm); | | 864 | error = route_output_report(rt, &info, rtm, &new_rtm); |
869 | if (error) | | 865 | if (error) |
870 | senderr(error); | | 866 | senderr(error); |
871 | if (new_rtm != NULL) { | | 867 | if (new_rtm != NULL) { |
872 | old_rtm = rtm; | | 868 | old_rtm = rtm; |
873 | rtm = new_rtm; | | 869 | rtm = new_rtm; |
874 | } | | 870 | } |
875 | break; | | 871 | break; |
876 | | | 872 | |
877 | case RTM_GET: | | 873 | case RTM_GET: |
878 | case RTM_CHANGE: | | 874 | case RTM_CHANGE: |
879 | case RTM_LOCK: | | 875 | case RTM_LOCK: |
880 | /* XXX This will mask info.rti_info[RTAX_DST] with | | 876 | /* XXX This will mask info.rti_info[RTAX_DST] with |
881 | * info.rti_info[RTAX_NETMASK] before | | 877 | * info.rti_info[RTAX_NETMASK] before |
882 | * searching. It did not used to do that. --dyoung | | 878 | * searching. It did not used to do that. --dyoung |
883 | */ | | 879 | */ |
884 | rt = NULL; | | 880 | rt = NULL; |
885 | error = rtrequest1(RTM_GET, &info, &rt); | | 881 | error = rtrequest1(RTM_GET, &info, &rt); |
886 | if (error != 0) | | 882 | if (error != 0) |
887 | senderr(error); | | 883 | senderr(error); |
888 | if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */ | | 884 | if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */ |
889 | if (memcmp(info.rti_info[RTAX_DST], rt_getkey(rt), | | 885 | if (memcmp(info.rti_info[RTAX_DST], rt_getkey(rt), |
890 | info.rti_info[RTAX_DST]->sa_len) != 0) | | 886 | info.rti_info[RTAX_DST]->sa_len) != 0) |
891 | senderr(ESRCH); | | 887 | senderr(ESRCH); |
892 | if (info.rti_info[RTAX_NETMASK] == NULL && | | 888 | if (info.rti_info[RTAX_NETMASK] == NULL && |
893 | rt_mask(rt) != NULL) | | 889 | rt_mask(rt) != NULL) |
894 | senderr(ETOOMANYREFS); | | 890 | senderr(ETOOMANYREFS); |
895 | } | | 891 | } |
896 | | | 892 | |
897 | /* | | 893 | /* |
898 | * XXX if arp/ndp requests an L2 entry, we have to obtain | | 894 | * XXX if arp/ndp requests an L2 entry, we have to obtain |
899 | * it from lltable while for the route command we have to | | 895 | * it from lltable while for the route command we have to |
900 | * return a route as it is. How to distinguish them? | | 896 | * return a route as it is. How to distinguish them? |
901 | * For newer arp/ndp, RTF_LLDATA flag set by arp/ndp | | 897 | * For newer arp/ndp, RTF_LLDATA flag set by arp/ndp |
902 | * indicates an L2 entry is requested. For old arp/ndp | | 898 | * indicates an L2 entry is requested. For old arp/ndp |
903 | * binaries, we check RTF_UP flag is NOT set; it works | | 899 | * binaries, we check RTF_UP flag is NOT set; it works |
904 | * by the fact that arp/ndp don't set it while the route | | 900 | * by the fact that arp/ndp don't set it while the route |
905 | * command sets it. | | 901 | * command sets it. |
906 | */ | | 902 | */ |
907 | if (((rtm->rtm_flags & RTF_LLDATA) != 0 || | | 903 | if (((rtm->rtm_flags & RTF_LLDATA) != 0 || |
908 | (rtm->rtm_flags & RTF_UP) == 0) && | | 904 | (rtm->rtm_flags & RTF_UP) == 0) && |
909 | rtm->rtm_type == RTM_GET && | | 905 | rtm->rtm_type == RTM_GET && |
910 | sockaddr_cmp(rt_getkey(rt), info.rti_info[RTAX_DST]) != 0) { | | 906 | sockaddr_cmp(rt_getkey(rt), info.rti_info[RTAX_DST]) != 0) { |
911 | int ll_flags = 0; | | 907 | int ll_flags = 0; |
912 | route_get_sdl(rt->rt_ifp, info.rti_info[RTAX_DST], &sdl, | | 908 | route_get_sdl(rt->rt_ifp, info.rti_info[RTAX_DST], &sdl, |
913 | &ll_flags); | | 909 | &ll_flags); |
914 | info.rti_info[RTAX_GATEWAY] = sstocsa(&sdl); | | 910 | info.rti_info[RTAX_GATEWAY] = sstocsa(&sdl); |
915 | error = route_output_report(rt, &info, rtm, &new_rtm); | | 911 | error = route_output_report(rt, &info, rtm, &new_rtm); |
916 | if (error) | | 912 | if (error) |
917 | senderr(error); | | 913 | senderr(error); |
918 | if (new_rtm != NULL) { | | 914 | if (new_rtm != NULL) { |
919 | old_rtm = rtm; | | 915 | old_rtm = rtm; |
920 | rtm = new_rtm; | | 916 | rtm = new_rtm; |
921 | } | | 917 | } |
922 | rtm->rtm_flags |= RTF_LLDATA; | | 918 | rtm->rtm_flags |= RTF_LLDATA; |
923 | rtm->rtm_flags |= (ll_flags & LLE_STATIC) ? RTF_STATIC : 0; | | 919 | rtm->rtm_flags |= (ll_flags & LLE_STATIC) ? RTF_STATIC : 0; |
924 | break; | | 920 | break; |
925 | } | | 921 | } |
926 | | | 922 | |
927 | switch (rtm->rtm_type) { | | 923 | switch (rtm->rtm_type) { |
928 | case RTM_GET: | | 924 | case RTM_GET: |
929 | info.rti_info[RTAX_DST] = rt_getkey(rt); | | 925 | info.rti_info[RTAX_DST] = rt_getkey(rt); |
930 | info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; | | 926 | info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; |
931 | info.rti_info[RTAX_NETMASK] = rt_mask(rt); | | 927 | info.rti_info[RTAX_NETMASK] = rt_mask(rt); |
932 | info.rti_info[RTAX_TAG] = rt_gettag(rt); | | 928 | info.rti_info[RTAX_TAG] = rt_gettag(rt); |
933 | error = route_output_report(rt, &info, rtm, &new_rtm); | | 929 | error = route_output_report(rt, &info, rtm, &new_rtm); |
934 | if (error) | | 930 | if (error) |
935 | senderr(error); | | 931 | senderr(error); |
936 | if (new_rtm != NULL) { | | 932 | if (new_rtm != NULL) { |
937 | old_rtm = rtm; | | 933 | old_rtm = rtm; |
938 | rtm = new_rtm; | | 934 | rtm = new_rtm; |
939 | } | | 935 | } |
940 | break; | | 936 | break; |
941 | | | 937 | |
942 | case RTM_CHANGE: | | 938 | case RTM_CHANGE: |
943 | #ifdef NET_MPSAFE | | 939 | #ifdef NET_MPSAFE |
944 | error = rt_update_prepare(rt); | | 940 | error = rt_update_prepare(rt); |
945 | if (error == 0) { | | 941 | if (error == 0) { |
946 | error = route_output_change(rt, &info, rtm); | | 942 | error = route_output_change(rt, &info, rtm); |
947 | rt_update_finish(rt); | | 943 | rt_update_finish(rt); |
948 | } | | 944 | } |
949 | #else | | 945 | #else |
950 | error = route_output_change(rt, &info, rtm); | | 946 | error = route_output_change(rt, &info, rtm); |
951 | #endif | | 947 | #endif |
952 | if (error != 0) | | 948 | if (error != 0) |
953 | goto flush; | | 949 | goto flush; |
954 | /*FALLTHROUGH*/ | | 950 | /*FALLTHROUGH*/ |
955 | case RTM_LOCK: | | 951 | case RTM_LOCK: |
956 | rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); | | 952 | rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits); |
957 | rt->rt_rmx.rmx_locks |= | | 953 | rt->rt_rmx.rmx_locks |= |
958 | (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); | | 954 | (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks); |
959 | break; | | 955 | break; |
960 | } | | 956 | } |
961 | break; | | 957 | break; |
962 | | | 958 | |
963 | default: | | 959 | default: |
964 | senderr(EOPNOTSUPP); | | 960 | senderr(EOPNOTSUPP); |
965 | } | | 961 | } |
966 | | | 962 | |
967 | flush: | | 963 | flush: |
968 | if (rtm) { | | 964 | if (rtm) { |
969 | if (error) | | 965 | if (error) |
970 | rtm->rtm_errno = error; | | 966 | rtm->rtm_errno = error; |
971 | else | | 967 | else |
972 | rtm->rtm_flags |= RTF_DONE; | | 968 | rtm->rtm_flags |= RTF_DONE; |
973 | } | | 969 | } |
974 | family = info.rti_info[RTAX_DST] ? info.rti_info[RTAX_DST]->sa_family : | | 970 | family = info.rti_info[RTAX_DST] ? info.rti_info[RTAX_DST]->sa_family : |
975 | 0; | | 971 | 0; |
976 | /* We cannot free old_rtm until we have stopped using the | | 972 | /* We cannot free old_rtm until we have stopped using the |
977 | * pointers in info, some of which may point to sockaddrs | | 973 | * pointers in info, some of which may point to sockaddrs |
978 | * in old_rtm. | | 974 | * in old_rtm. |
979 | */ | | 975 | */ |
980 | if (old_rtm != NULL) | | 976 | if (old_rtm != NULL) |
981 | Free(old_rtm); | | 977 | Free(old_rtm); |
982 | if (rt) { | | 978 | if (rt) { |
983 | if (do_rt_free) | | 979 | if (do_rt_free) |
984 | rt_free(rt); | | 980 | rt_free(rt); |
985 | else | | 981 | else |
986 | rt_unref(rt); | | 982 | rt_unref(rt); |
987 | } | | 983 | } |
988 | { | | 984 | { |
989 | struct rawcb *rp = NULL; | | 985 | struct rawcb *rp = NULL; |
990 | /* | | 986 | /* |
991 | * Check to see if we don't want our own messages. | | 987 | * Check to see if we don't want our own messages. |
992 | */ | | 988 | */ |
993 | if ((so->so_options & SO_USELOOPBACK) == 0) { | | 989 | if ((so->so_options & SO_USELOOPBACK) == 0) { |
994 | if (COMPATNAME(route_info).ri_cb.any_count <= 1) { | | 990 | if (COMPATNAME(route_info).ri_cb.any_count <= 1) { |
995 | if (rtm) | | 991 | if (rtm) |
996 | Free(rtm); | | 992 | Free(rtm); |
997 | m_freem(m); | | 993 | m_freem(m); |
998 | goto out; | | 994 | goto out; |
999 | } | | 995 | } |
1000 | /* There is another listener, so construct message */ | | 996 | /* There is another listener, so construct message */ |
1001 | rp = sotorawcb(so); | | 997 | rp = sotorawcb(so); |
1002 | } | | 998 | } |
1003 | if (rtm) { | | 999 | if (rtm) { |
1004 | m_copyback(m, 0, rtm->rtm_msglen, rtm); | | 1000 | m_copyback(m, 0, rtm->rtm_msglen, rtm); |
1005 | if (m->m_pkthdr.len < rtm->rtm_msglen) { | | 1001 | if (m->m_pkthdr.len < rtm->rtm_msglen) { |
1006 | m_freem(m); | | 1002 | m_freem(m); |
1007 | m = NULL; | | 1003 | m = NULL; |
1008 | } else if (m->m_pkthdr.len > rtm->rtm_msglen) | | 1004 | } else if (m->m_pkthdr.len > rtm->rtm_msglen) |
1009 | m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); | | 1005 | m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); |
1010 | Free(rtm); | | 1006 | Free(rtm); |
1011 | } | | 1007 | } |
1012 | if (rp) | | 1008 | if (rp) |
1013 | rp->rcb_proto.sp_family = 0; /* Avoid us */ | | 1009 | rp->rcb_proto.sp_family = 0; /* Avoid us */ |
1014 | if (family) | | 1010 | if (family) |
1015 | proto.sp_protocol = family; | | 1011 | proto.sp_protocol = family; |
1016 | if (m) | | 1012 | if (m) |
1017 | raw_input(m, &proto, &COMPATNAME(route_info).ri_src, | | 1013 | raw_input(m, &proto, &COMPATNAME(route_info).ri_src, |
1018 | &COMPATNAME(route_info).ri_dst); | | 1014 | &COMPATNAME(route_info).ri_dst); |
1019 | if (rp) | | 1015 | if (rp) |
1020 | rp->rcb_proto.sp_family = PF_XROUTE; | | 1016 | rp->rcb_proto.sp_family = PF_XROUTE; |
1021 | } | | 1017 | } |
1022 | out: | | 1018 | out: |
1023 | curlwp_bindx(bound); | | 1019 | curlwp_bindx(bound); |
1024 | return error; | | 1020 | return error; |
1025 | } | | 1021 | } |
1026 | | | 1022 | |
1027 | static int | | 1023 | static int |
1028 | route_ctloutput(int op, struct socket *so, struct sockopt *sopt) | | 1024 | route_ctloutput(int op, struct socket *so, struct sockopt *sopt) |
1029 | { | | 1025 | { |
1030 | struct routecb *rop = sotoroutecb(so); | | 1026 | struct routecb *rop = sotoroutecb(so); |
1031 | int error = 0; | | 1027 | int error = 0; |
1032 | unsigned char *rtm_type; | | 1028 | unsigned char *rtm_type; |
1033 | size_t len; | | 1029 | size_t len; |
1034 | unsigned int msgfilter; | | 1030 | unsigned int msgfilter; |
1035 | | | 1031 | |
1036 | KASSERT(solocked(so)); | | 1032 | KASSERT(solocked(so)); |
1037 | | | 1033 | |
1038 | if (sopt->sopt_level != AF_ROUTE) { | | 1034 | if (sopt->sopt_level != AF_ROUTE) { |
1039 | error = ENOPROTOOPT; | | 1035 | error = ENOPROTOOPT; |
1040 | } else switch (op) { | | 1036 | } else switch (op) { |
1041 | case PRCO_SETOPT: | | 1037 | case PRCO_SETOPT: |
1042 | switch (sopt->sopt_name) { | | 1038 | switch (sopt->sopt_name) { |
1043 | case RO_MSGFILTER: | | 1039 | case RO_MSGFILTER: |
1044 | msgfilter = 0; | | 1040 | msgfilter = 0; |
1045 | for (rtm_type = sopt->sopt_data, len = sopt->sopt_size; | | 1041 | for (rtm_type = sopt->sopt_data, len = sopt->sopt_size; |
1046 | len != 0; | | 1042 | len != 0; |
1047 | rtm_type++, len -= sizeof(*rtm_type)) | | 1043 | rtm_type++, len -= sizeof(*rtm_type)) |
1048 | { | | 1044 | { |
1049 | /* Guard against overflowing our storage. */ | | 1045 | /* Guard against overflowing our storage. */ |
1050 | if (*rtm_type >= sizeof(msgfilter) * CHAR_BIT) { | | 1046 | if (*rtm_type >= sizeof(msgfilter) * CHAR_BIT) { |
1051 | error = EOVERFLOW; | | 1047 | error = EOVERFLOW; |
1052 | break; | | 1048 | break; |
1053 | } | | 1049 | } |
1054 | msgfilter |= RTMSGFILTER(*rtm_type); | | 1050 | msgfilter |= RTMSGFILTER(*rtm_type); |
1055 | } | | 1051 | } |
1056 | if (error == 0) | | 1052 | if (error == 0) |
1057 | rop->rocb_msgfilter = msgfilter; | | 1053 | rop->rocb_msgfilter = msgfilter; |
1058 | break; | | 1054 | break; |
1059 | default: | | 1055 | default: |
1060 | error = ENOPROTOOPT; | | 1056 | error = ENOPROTOOPT; |
1061 | break; | | 1057 | break; |
1062 | } | | 1058 | } |
1063 | break; | | 1059 | break; |
1064 | case PRCO_GETOPT: | | 1060 | case PRCO_GETOPT: |
1065 | switch (sopt->sopt_name) { | | 1061 | switch (sopt->sopt_name) { |
1066 | case RO_MSGFILTER: | | 1062 | case RO_MSGFILTER: |
1067 | error = ENOTSUP; | | 1063 | error = ENOTSUP; |
1068 | break; | | 1064 | break; |
1069 | default: | | 1065 | default: |
1070 | error = ENOPROTOOPT; | | 1066 | error = ENOPROTOOPT; |
1071 | break; | | 1067 | break; |
1072 | } | | 1068 | } |
1073 | } | | 1069 | } |
1074 | return error; | | 1070 | return error; |
1075 | } | | 1071 | } |
1076 | | | 1072 | |
1077 | static void | | 1073 | static void |
1078 | rt_setmetrics(int which, const struct rt_xmsghdr *in, struct rtentry *out) | | 1074 | rt_setmetrics(int which, const struct rt_xmsghdr *in, struct rtentry *out) |
1079 | { | | 1075 | { |
1080 | #define metric(f, e) if (which & (f)) out->rt_rmx.e = in->rtm_rmx.e; | | 1076 | #define metric(f, e) if (which & (f)) out->rt_rmx.e = in->rtm_rmx.e; |
1081 | metric(RTV_RPIPE, rmx_recvpipe); | | 1077 | metric(RTV_RPIPE, rmx_recvpipe); |
1082 | metric(RTV_SPIPE, rmx_sendpipe); | | 1078 | metric(RTV_SPIPE, rmx_sendpipe); |
1083 | metric(RTV_SSTHRESH, rmx_ssthresh); | | 1079 | metric(RTV_SSTHRESH, rmx_ssthresh); |
1084 | metric(RTV_RTT, rmx_rtt); | | 1080 | metric(RTV_RTT, rmx_rtt); |
1085 | metric(RTV_RTTVAR, rmx_rttvar); | | 1081 | metric(RTV_RTTVAR, rmx_rttvar); |
1086 | metric(RTV_HOPCOUNT, rmx_hopcount); | | 1082 | metric(RTV_HOPCOUNT, rmx_hopcount); |
1087 | metric(RTV_MTU, rmx_mtu); | | 1083 | metric(RTV_MTU, rmx_mtu); |
1088 | #undef metric | | 1084 | #undef metric |
1089 | if (which & RTV_EXPIRE) { | | 1085 | if (which & RTV_EXPIRE) { |
1090 | out->rt_rmx.rmx_expire = in->rtm_rmx.rmx_expire ? | | 1086 | out->rt_rmx.rmx_expire = in->rtm_rmx.rmx_expire ? |
1091 | time_wall_to_mono(in->rtm_rmx.rmx_expire) : 0; | | 1087 | time_wall_to_mono(in->rtm_rmx.rmx_expire) : 0; |
1092 | } | | 1088 | } |
1093 | } | | 1089 | } |
1094 | | | 1090 | |
1095 | static void | | 1091 | static void |
1096 | rtm_setmetrics(const struct rtentry *in, struct rt_xmsghdr *out) | | 1092 | rtm_setmetrics(const struct rtentry *in, struct rt_xmsghdr *out) |
1097 | { | | 1093 | { |
1098 | #define metric(e) out->rtm_rmx.e = in->rt_rmx.e; | | 1094 | #define metric(e) out->rtm_rmx.e = in->rt_rmx.e; |
1099 | metric(rmx_recvpipe); | | 1095 | metric(rmx_recvpipe); |
1100 | metric(rmx_sendpipe); | | 1096 | metric(rmx_sendpipe); |
1101 | metric(rmx_ssthresh); | | 1097 | metric(rmx_ssthresh); |
1102 | metric(rmx_rtt); | | 1098 | metric(rmx_rtt); |
1103 | metric(rmx_rttvar); | | 1099 | metric(rmx_rttvar); |
1104 | metric(rmx_hopcount); | | 1100 | metric(rmx_hopcount); |
1105 | metric(rmx_mtu); | | 1101 | metric(rmx_mtu); |
1106 | metric(rmx_locks); | | 1102 | metric(rmx_locks); |
1107 | #undef metric | | 1103 | #undef metric |
1108 | out->rtm_rmx.rmx_expire = in->rt_rmx.rmx_expire ? | | 1104 | out->rtm_rmx.rmx_expire = in->rt_rmx.rmx_expire ? |
1109 | time_mono_to_wall(in->rt_rmx.rmx_expire) : 0; | | 1105 | time_mono_to_wall(in->rt_rmx.rmx_expire) : 0; |
1110 | } | | 1106 | } |
1111 | | | 1107 | |
1112 | static int | | 1108 | static int |
1113 | rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim, | | 1109 | rt_xaddrs(u_char rtmtype, const char *cp, const char *cplim, |
1114 | struct rt_addrinfo *rtinfo) | | 1110 | struct rt_addrinfo *rtinfo) |
1115 | { | | 1111 | { |
1116 | const struct sockaddr *sa = NULL; /* Quell compiler warning */ | | 1112 | const struct sockaddr *sa = NULL; /* Quell compiler warning */ |
1117 | int i; | | 1113 | int i; |
1118 | | | 1114 | |
1119 | for (i = 0; i < RTAX_MAX && cp < cplim; i++) { | | 1115 | for (i = 0; i < RTAX_MAX && cp < cplim; i++) { |
1120 | if ((rtinfo->rti_addrs & (1 << i)) == 0) | | 1116 | if ((rtinfo->rti_addrs & (1 << i)) == 0) |
1121 | continue; | | 1117 | continue; |
1122 | rtinfo->rti_info[i] = sa = (const struct sockaddr *)cp; | | 1118 | rtinfo->rti_info[i] = sa = (const struct sockaddr *)cp; |
1123 | RT_XADVANCE(cp, sa); | | 1119 | RT_XADVANCE(cp, sa); |
1124 | } | | 1120 | } |
1125 | | | 1121 | |
1126 | /* | | 1122 | /* |
1127 | * Check for extra addresses specified, except RTM_GET asking | | 1123 | * Check for extra addresses specified, except RTM_GET asking |
1128 | * for interface info. | | 1124 | * for interface info. |
1129 | */ | | 1125 | */ |
1130 | if (rtmtype == RTM_GET) { | | 1126 | if (rtmtype == RTM_GET) { |
1131 | if (((rtinfo->rti_addrs & | | 1127 | if (((rtinfo->rti_addrs & |
1132 | (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0U << i)) != 0) | | 1128 | (~((1 << RTAX_IFP) | (1 << RTAX_IFA)))) & (~0U << i)) != 0) |
1133 | return 1; | | 1129 | return 1; |
1134 | } else if ((rtinfo->rti_addrs & (~0U << i)) != 0) | | 1130 | } else if ((rtinfo->rti_addrs & (~0U << i)) != 0) |
1135 | return 1; | | 1131 | return 1; |
1136 | /* Check for bad data length. */ | | 1132 | /* Check for bad data length. */ |
1137 | if (cp != cplim) { | | 1133 | if (cp != cplim) { |
1138 | if (i == RTAX_NETMASK + 1 && sa != NULL && | | 1134 | if (i == RTAX_NETMASK + 1 && sa != NULL && |
1139 | cp - RT_XROUNDUP(sa->sa_len) + sa->sa_len == cplim) | | 1135 | cp - RT_XROUNDUP(sa->sa_len) + sa->sa_len == cplim) |
1140 | /* | | 1136 | /* |
1141 | * The last sockaddr was info.rti_info[RTAX_NETMASK]. | | 1137 | * The last sockaddr was info.rti_info[RTAX_NETMASK]. |
1142 | * We accept this for now for the sake of old | | 1138 | * We accept this for now for the sake of old |
1143 | * binaries or third party softwares. | | 1139 | * binaries or third party softwares. |
1144 | */ | | 1140 | */ |
1145 | ; | | 1141 | ; |
1146 | else | | 1142 | else |
1147 | return 1; | | 1143 | return 1; |
1148 | } | | 1144 | } |
1149 | return 0; | | 1145 | return 0; |
1150 | } | | 1146 | } |
1151 | | | 1147 | |
1152 | static int | | 1148 | static int |
1153 | rt_getlen(int type) | | 1149 | rt_getlen(int type) |
1154 | { | | 1150 | { |
1155 | #ifndef COMPAT_RTSOCK | | 1151 | #ifndef COMPAT_RTSOCK |
1156 | CTASSERT(__alignof(struct ifa_msghdr) >= sizeof(uint64_t)); | | 1152 | CTASSERT(__alignof(struct ifa_msghdr) >= sizeof(uint64_t)); |
1157 | CTASSERT(__alignof(struct if_msghdr) >= sizeof(uint64_t)); | | 1153 | CTASSERT(__alignof(struct if_msghdr) >= sizeof(uint64_t)); |
1158 | CTASSERT(__alignof(struct if_announcemsghdr) >= sizeof(uint64_t)); | | 1154 | CTASSERT(__alignof(struct if_announcemsghdr) >= sizeof(uint64_t)); |
1159 | CTASSERT(__alignof(struct rt_msghdr) >= sizeof(uint64_t)); | | 1155 | CTASSERT(__alignof(struct rt_msghdr) >= sizeof(uint64_t)); |
1160 | #endif | | 1156 | #endif |
1161 | | | 1157 | |
1162 | switch (type) { | | 1158 | switch (type) { |
1163 | case RTM_ODELADDR: | | 1159 | case RTM_ODELADDR: |
1164 | case RTM_ONEWADDR: | | 1160 | case RTM_ONEWADDR: |
1165 | case RTM_OCHGADDR: | | 1161 | case RTM_OCHGADDR: |
1166 | #ifdef COMPAT_70 | | 1162 | #ifdef COMPAT_70 |
1167 | return sizeof(struct ifa_msghdr70); | | 1163 | return sizeof(struct ifa_msghdr70); |
1168 | #else | | 1164 | #else |
1169 | #ifdef RTSOCK_DEBUG | | 1165 | #ifdef RTSOCK_DEBUG |
1170 | printf("%s: unsupported RTM type %d\n", __func__, type); | | 1166 | printf("%s: unsupported RTM type %d\n", __func__, type); |
1171 | #endif | | 1167 | #endif |
1172 | return -1; | | 1168 | return -1; |
1173 | #endif | | 1169 | #endif |
1174 | case RTM_DELADDR: | | 1170 | case RTM_DELADDR: |
1175 | case RTM_NEWADDR: | | 1171 | case RTM_NEWADDR: |
1176 | case RTM_CHGADDR: | | 1172 | case RTM_CHGADDR: |
1177 | return sizeof(struct ifa_xmsghdr); | | 1173 | return sizeof(struct ifa_xmsghdr); |
1178 | | | 1174 | |
1179 | case RTM_OOIFINFO: | | 1175 | case RTM_OOIFINFO: |
1180 | #ifdef COMPAT_14 | | 1176 | #ifdef COMPAT_14 |
1181 | return sizeof(struct if_msghdr14); | | 1177 | return sizeof(struct if_msghdr14); |
1182 | #else | | 1178 | #else |
1183 | #ifdef RTSOCK_DEBUG | | 1179 | #ifdef RTSOCK_DEBUG |
1184 | printf("%s: unsupported RTM type RTM_OOIFINFO\n", __func__); | | 1180 | printf("%s: unsupported RTM type RTM_OOIFINFO\n", __func__); |
1185 | #endif | | 1181 | #endif |
1186 | return -1; | | 1182 | return -1; |
1187 | #endif | | 1183 | #endif |
1188 | case RTM_OIFINFO: | | 1184 | case RTM_OIFINFO: |
1189 | #ifdef COMPAT_50 | | 1185 | #ifdef COMPAT_50 |
1190 | return sizeof(struct if_msghdr50); | | 1186 | return sizeof(struct if_msghdr50); |
1191 | #else | | 1187 | #else |
1192 | #ifdef RTSOCK_DEBUG | | 1188 | #ifdef RTSOCK_DEBUG |
1193 | printf("%s: unsupported RTM type RTM_OIFINFO\n", __func__); | | 1189 | printf("%s: unsupported RTM type RTM_OIFINFO\n", __func__); |
1194 | #endif | | 1190 | #endif |
1195 | return -1; | | 1191 | return -1; |
1196 | #endif | | 1192 | #endif |
1197 | | | 1193 | |
1198 | case RTM_IFINFO: | | 1194 | case RTM_IFINFO: |
1199 | return sizeof(struct if_xmsghdr); | | 1195 | return sizeof(struct if_xmsghdr); |
1200 | | | 1196 | |
1201 | case RTM_IFANNOUNCE: | | 1197 | case RTM_IFANNOUNCE: |
1202 | case RTM_IEEE80211: | | 1198 | case RTM_IEEE80211: |
1203 | return sizeof(struct if_xannouncemsghdr); | | 1199 | return sizeof(struct if_xannouncemsghdr); |
1204 | | | 1200 | |
1205 | default: | | 1201 | default: |
1206 | return sizeof(struct rt_xmsghdr); | | 1202 | return sizeof(struct rt_xmsghdr); |
1207 | } | | 1203 | } |
1208 | } | | 1204 | } |
1209 | | | 1205 | |
1210 | | | 1206 | |
1211 | struct mbuf * | | 1207 | struct mbuf * |
1212 | COMPATNAME(rt_msg1)(int type, struct rt_addrinfo *rtinfo, void *data, int datalen) | | 1208 | COMPATNAME(rt_msg1)(int type, struct rt_addrinfo *rtinfo, void *data, int datalen) |
1213 | { | | 1209 | { |
1214 | struct rt_xmsghdr *rtm; | | 1210 | struct rt_xmsghdr *rtm; |
1215 | struct mbuf *m; | | 1211 | struct mbuf *m; |
1216 | int i; | | 1212 | int i; |
1217 | const struct sockaddr *sa; | | 1213 | const struct sockaddr *sa; |
1218 | int len, dlen; | | 1214 | int len, dlen; |
1219 | | | 1215 | |
1220 | m = m_gethdr(M_DONTWAIT, MT_DATA); | | 1216 | m = m_gethdr(M_DONTWAIT, MT_DATA); |
1221 | if (m == NULL) | | 1217 | if (m == NULL) |
1222 | return m; | | 1218 | return m; |
1223 | MCLAIM(m, &COMPATNAME(routedomain).dom_mowner); | | 1219 | MCLAIM(m, &COMPATNAME(routedomain).dom_mowner); |
1224 | | | 1220 | |
1225 | if ((len = rt_getlen(type)) == -1) | | 1221 | if ((len = rt_getlen(type)) == -1) |
1226 | goto out; | | 1222 | goto out; |
1227 | if (len > MHLEN + MLEN) | | 1223 | if (len > MHLEN + MLEN) |
1228 | panic("%s: message too long", __func__); | | 1224 | panic("%s: message too long", __func__); |
1229 | else if (len > MHLEN) { | | 1225 | else if (len > MHLEN) { |
1230 | m->m_next = m_get(M_DONTWAIT, MT_DATA); | | 1226 | m->m_next = m_get(M_DONTWAIT, MT_DATA); |
1231 | if (m->m_next == NULL) | | 1227 | if (m->m_next == NULL) |
1232 | goto out; | | 1228 | goto out; |
1233 | MCLAIM(m->m_next, m->m_owner); | | 1229 | MCLAIM(m->m_next, m->m_owner); |
1234 | m->m_pkthdr.len = len; | | 1230 | m->m_pkthdr.len = len; |
1235 | m->m_len = MHLEN; | | 1231 | m->m_len = MHLEN; |
1236 | m->m_next->m_len = len - MHLEN; | | 1232 | m->m_next->m_len = len - MHLEN; |
1237 | } else { | | 1233 | } else { |
1238 | m->m_pkthdr.len = m->m_len = len; | | 1234 | m->m_pkthdr.len = m->m_len = len; |
1239 | } | | 1235 | } |
1240 | m_reset_rcvif(m); | | 1236 | m_reset_rcvif(m); |
1241 | m_copyback(m, 0, datalen, data); | | 1237 | m_copyback(m, 0, datalen, data); |
1242 | if (len > datalen) | | 1238 | if (len > datalen) |
1243 | (void)memset(mtod(m, char *) + datalen, 0, len - datalen); | | 1239 | (void)memset(mtod(m, char *) + datalen, 0, len - datalen); |
1244 | rtm = mtod(m, struct rt_xmsghdr *); | | 1240 | rtm = mtod(m, struct rt_xmsghdr *); |
1245 | for (i = 0; i < RTAX_MAX; i++) { | | 1241 | for (i = 0; i < RTAX_MAX; i++) { |
1246 | if ((sa = rtinfo->rti_info[i]) == NULL) | | 1242 | if ((sa = rtinfo->rti_info[i]) == NULL) |
1247 | continue; | | 1243 | continue; |
1248 | rtinfo->rti_addrs |= (1 << i); | | 1244 | rtinfo->rti_addrs |= (1 << i); |
1249 | dlen = RT_XROUNDUP(sa->sa_len); | | 1245 | dlen = RT_XROUNDUP(sa->sa_len); |
1250 | m_copyback(m, len, sa->sa_len, sa); | | 1246 | m_copyback(m, len, sa->sa_len, sa); |
1251 | if (dlen != sa->sa_len) { | | 1247 | if (dlen != sa->sa_len) { |
1252 | /* | | 1248 | /* |
1253 | * Up to 6 + 1 nul's since roundup is to | | 1249 | * Up to 6 + 1 nul's since roundup is to |
1254 | * sizeof(uint64_t) (8 bytes) | | 1250 | * sizeof(uint64_t) (8 bytes) |
1255 | */ | | 1251 | */ |
1256 | m_copyback(m, len + sa->sa_len, | | 1252 | m_copyback(m, len + sa->sa_len, |
1257 | dlen - sa->sa_len, "\0\0\0\0\0\0"); | | 1253 | dlen - sa->sa_len, "\0\0\0\0\0\0"); |
1258 | } | | 1254 | } |
1259 | len += dlen; | | 1255 | len += dlen; |
1260 | } | | 1256 | } |
1261 | if (m->m_pkthdr.len != len) | | 1257 | if (m->m_pkthdr.len != len) |
1262 | goto out; | | 1258 | goto out; |
1263 | rtm->rtm_msglen = len; | | 1259 | rtm->rtm_msglen = len; |
1264 | rtm->rtm_version = RTM_XVERSION; | | 1260 | rtm->rtm_version = RTM_XVERSION; |
1265 | rtm->rtm_type = type; | | 1261 | rtm->rtm_type = type; |
1266 | return m; | | 1262 | return m; |
1267 | out: | | 1263 | out: |
1268 | m_freem(m); | | 1264 | m_freem(m); |
1269 | return NULL; | | 1265 | return NULL; |
1270 | } | | 1266 | } |
1271 | | | 1267 | |
1272 | /* | | 1268 | /* |
1273 | * rt_msg2 | | 1269 | * rt_msg2 |
1274 | * | | 1270 | * |
1275 | * fills 'cp' or 'w'.w_tmem with the routing socket message and | | 1271 | * fills 'cp' or 'w'.w_tmem with the routing socket message and |
1276 | * returns the length of the message in 'lenp'. | | 1272 | * returns the length of the message in 'lenp'. |
1277 | * | | 1273 | * |
1278 | * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold | | 1274 | * if walkarg is 0, cp is expected to be 0 or a buffer large enough to hold |
1279 | * the message | | 1275 | * the message |
1280 | * otherwise walkarg's w_needed is updated and if the user buffer is | | 1276 | * otherwise walkarg's w_needed is updated and if the user buffer is |
1281 | * specified and w_needed indicates space exists the information is copied | | 1277 | * specified and w_needed indicates space exists the information is copied |
1282 | * into the temp space (w_tmem). w_tmem is [re]allocated if necessary, | | 1278 | * into the temp space (w_tmem). w_tmem is [re]allocated if necessary, |
1283 | * if the allocation fails ENOBUFS is returned. | | 1279 | * if the allocation fails ENOBUFS is returned. |
1284 | */ | | 1280 | */ |
1285 | static int | | 1281 | static int |
1286 | rt_msg2(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w, | | 1282 | rt_msg2(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w, |
1287 | int *lenp) | | 1283 | int *lenp) |
1288 | { | | 1284 | { |
1289 | int i; | | 1285 | int i; |
1290 | int len, dlen, second_time = 0; | | 1286 | int len, dlen, second_time = 0; |
1291 | char *cp0, *cp = cpv; | | 1287 | char *cp0, *cp = cpv; |
1292 | | | 1288 | |
1293 | rtinfo->rti_addrs = 0; | | 1289 | rtinfo->rti_addrs = 0; |
1294 | again: | | 1290 | again: |
1295 | if ((len = rt_getlen(type)) == -1) | | 1291 | if ((len = rt_getlen(type)) == -1) |
1296 | return EINVAL; | | 1292 | return EINVAL; |
1297 | | | 1293 | |
1298 | if ((cp0 = cp) != NULL) | | 1294 | if ((cp0 = cp) != NULL) |
1299 | cp += len; | | 1295 | cp += len; |
1300 | for (i = 0; i < RTAX_MAX; i++) { | | 1296 | for (i = 0; i < RTAX_MAX; i++) { |
1301 | const struct sockaddr *sa; | | 1297 | const struct sockaddr *sa; |
1302 | | | 1298 | |
1303 | if ((sa = rtinfo->rti_info[i]) == NULL) | | 1299 | if ((sa = rtinfo->rti_info[i]) == NULL) |
1304 | continue; | | 1300 | continue; |
1305 | rtinfo->rti_addrs |= (1 << i); | | 1301 | rtinfo->rti_addrs |= (1 << i); |
1306 | dlen = RT_XROUNDUP(sa->sa_len); | | 1302 | dlen = RT_XROUNDUP(sa->sa_len); |
1307 | if (cp) { | | 1303 | if (cp) { |
1308 | int diff = dlen - sa->sa_len; | | 1304 | int diff = dlen - sa->sa_len; |
1309 | (void)memcpy(cp, sa, (size_t)sa->sa_len); | | 1305 | (void)memcpy(cp, sa, (size_t)sa->sa_len); |
1310 | cp += sa->sa_len; | | 1306 | cp += sa->sa_len; |
1311 | if (diff > 0) { | | 1307 | if (diff > 0) { |
1312 | (void)memset(cp, 0, (size_t)diff); | | 1308 | (void)memset(cp, 0, (size_t)diff); |
1313 | cp += diff; | | 1309 | cp += diff; |
1314 | } | | 1310 | } |
1315 | } | | 1311 | } |
1316 | len += dlen; | | 1312 | len += dlen; |
1317 | } | | 1313 | } |
1318 | if (cp == NULL && w != NULL && !second_time) { | | 1314 | if (cp == NULL && w != NULL && !second_time) { |
1319 | struct rt_walkarg *rw = w; | | 1315 | struct rt_walkarg *rw = w; |
1320 | | | 1316 | |
1321 | rw->w_needed += len; | | 1317 | rw->w_needed += len; |
1322 | if (rw->w_needed <= 0 && rw->w_where) { | | 1318 | if (rw->w_needed <= 0 && rw->w_where) { |
1323 | if (rw->w_tmemsize < len) { | | 1319 | if (rw->w_tmemsize < len) { |
1324 | if (rw->w_tmem) | | 1320 | if (rw->w_tmem) |
1325 | kmem_free(rw->w_tmem, rw->w_tmemsize); | | 1321 | kmem_free(rw->w_tmem, rw->w_tmemsize); |
1326 | rw->w_tmem = kmem_alloc(len, KM_SLEEP); | | 1322 | rw->w_tmem = kmem_alloc(len, KM_SLEEP); |
1327 | rw->w_tmemsize = len; | | 1323 | rw->w_tmemsize = len; |
1328 | } | | 1324 | } |
1329 | if (rw->w_tmem) { | | 1325 | if (rw->w_tmem) { |
1330 | cp = rw->w_tmem; | | 1326 | cp = rw->w_tmem; |
1331 | second_time = 1; | | 1327 | second_time = 1; |
1332 | goto again; | | 1328 | goto again; |
1333 | } else { | | 1329 | } else { |
1334 | rw->w_tmemneeded = len; | | 1330 | rw->w_tmemneeded = len; |
1335 | return ENOBUFS; | | 1331 | return ENOBUFS; |
1336 | } | | 1332 | } |
1337 | } | | 1333 | } |
1338 | } | | 1334 | } |
1339 | if (cp) { | | 1335 | if (cp) { |
1340 | struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)cp0; | | 1336 | struct rt_xmsghdr *rtm = (struct rt_xmsghdr *)cp0; |
1341 | | | 1337 | |
1342 | rtm->rtm_version = RTM_XVERSION; | | 1338 | rtm->rtm_version = RTM_XVERSION; |
1343 | rtm->rtm_type = type; | | 1339 | rtm->rtm_type = type; |
1344 | rtm->rtm_msglen = len; | | 1340 | rtm->rtm_msglen = len; |
1345 | } | | 1341 | } |
1346 | if (lenp) | | 1342 | if (lenp) |
1347 | *lenp = len; | | 1343 | *lenp = len; |
1348 | return 0; | | 1344 | return 0; |
1349 | } | | 1345 | } |
1350 | | | 1346 | |
1351 | #ifndef COMPAT_RTSOCK | | 1347 | #ifndef COMPAT_RTSOCK |
1352 | int | | 1348 | int |
1353 | rt_msg3(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w, | | 1349 | rt_msg3(int type, struct rt_addrinfo *rtinfo, void *cpv, struct rt_walkarg *w, |
1354 | int *lenp) | | 1350 | int *lenp) |
1355 | { | | 1351 | { |
1356 | return rt_msg2(type, rtinfo, cpv, w, lenp); | | 1352 | return rt_msg2(type, rtinfo, cpv, w, lenp); |
1357 | } | | 1353 | } |
1358 | #endif | | 1354 | #endif |
1359 | | | 1355 | |
1360 | /* | | 1356 | /* |
1361 | * This routine is called to generate a message from the routing | | 1357 | * This routine is called to generate a message from the routing |
1362 | * socket indicating that a redirect has occurred, a routing lookup | | 1358 | * socket indicating that a redirect has occurred, a routing lookup |
1363 | * has failed, or that a protocol has detected timeouts to a particular | | 1359 | * has failed, or that a protocol has detected timeouts to a particular |
1364 | * destination. | | 1360 | * destination. |
1365 | */ | | 1361 | */ |
1366 | void | | 1362 | void |
1367 | COMPATNAME(rt_missmsg)(int type, const struct rt_addrinfo *rtinfo, int flags, | | 1363 | COMPATNAME(rt_missmsg)(int type, const struct rt_addrinfo *rtinfo, int flags, |
1368 | int error) | | 1364 | int error) |
1369 | { | | 1365 | { |
1370 | struct rt_xmsghdr rtm; | | 1366 | struct rt_xmsghdr rtm; |
1371 | struct mbuf *m; | | 1367 | struct mbuf *m; |
1372 | const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; | | 1368 | const struct sockaddr *sa = rtinfo->rti_info[RTAX_DST]; |
1373 | struct rt_addrinfo info = *rtinfo; | | 1369 | struct rt_addrinfo info = *rtinfo; |
1374 | | | 1370 | |
1375 | COMPATCALL(rt_missmsg, (type, rtinfo, flags, error)); | | 1371 | COMPATCALL(rt_missmsg, (type, rtinfo, flags, error)); |
1376 | if (COMPATNAME(route_info).ri_cb.any_count == 0) | | 1372 | if (COMPATNAME(route_info).ri_cb.any_count == 0) |
1377 | return; | | 1373 | return; |
1378 | memset(&rtm, 0, sizeof(rtm)); | | 1374 | memset(&rtm, 0, sizeof(rtm)); |
1379 | rtm.rtm_pid = curproc->p_pid; | | 1375 | rtm.rtm_pid = curproc->p_pid; |
1380 | rtm.rtm_flags = RTF_DONE | flags; | | 1376 | rtm.rtm_flags = RTF_DONE | flags; |
1381 | rtm.rtm_errno = error; | | 1377 | rtm.rtm_errno = error; |
1382 | m = COMPATNAME(rt_msg1)(type, &info, &rtm, sizeof(rtm)); | | 1378 | m = COMPATNAME(rt_msg1)(type, &info, &rtm, sizeof(rtm)); |
1383 | if (m == NULL) | | 1379 | if (m == NULL) |
1384 | return; | | 1380 | return; |
1385 | mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs; | | 1381 | mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs; |
1386 | COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0); | | 1382 | COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0); |
1387 | } | | 1383 | } |
1388 | | | 1384 | |
1389 | /* | | 1385 | /* |
1390 | * This routine is called to generate a message from the routing | | 1386 | * This routine is called to generate a message from the routing |
1391 | * socket indicating that the status of a network interface has changed. | | 1387 | * socket indicating that the status of a network interface has changed. |
1392 | */ | | 1388 | */ |
1393 | void | | 1389 | void |
1394 | COMPATNAME(rt_ifmsg)(struct ifnet *ifp) | | 1390 | COMPATNAME(rt_ifmsg)(struct ifnet *ifp) |
1395 | { | | 1391 | { |
1396 | struct if_xmsghdr ifm; | | 1392 | struct if_xmsghdr ifm; |
1397 | struct mbuf *m; | | 1393 | struct mbuf *m; |
1398 | struct rt_addrinfo info; | | 1394 | struct rt_addrinfo info; |
1399 | | | 1395 | |
1400 | COMPATCALL(rt_ifmsg, (ifp)); | | 1396 | COMPATCALL(rt_ifmsg, (ifp)); |
1401 | if (COMPATNAME(route_info).ri_cb.any_count == 0) | | 1397 | if (COMPATNAME(route_info).ri_cb.any_count == 0) |
1402 | return; | | 1398 | return; |
1403 | (void)memset(&info, 0, sizeof(info)); | | 1399 | (void)memset(&info, 0, sizeof(info)); |
1404 | (void)memset(&ifm, 0, sizeof(ifm)); | | 1400 | (void)memset(&ifm, 0, sizeof(ifm)); |
1405 | ifm.ifm_index = ifp->if_index; | | 1401 | ifm.ifm_index = ifp->if_index; |
1406 | ifm.ifm_flags = ifp->if_flags; | | 1402 | ifm.ifm_flags = ifp->if_flags; |
1407 | ifm.ifm_data = ifp->if_data; | | 1403 | ifm.ifm_data = ifp->if_data; |
1408 | ifm.ifm_addrs = 0; | | 1404 | ifm.ifm_addrs = 0; |
1409 | m = COMPATNAME(rt_msg1)(RTM_IFINFO, &info, &ifm, sizeof(ifm)); | | 1405 | m = COMPATNAME(rt_msg1)(RTM_IFINFO, &info, &ifm, sizeof(ifm)); |
1410 | if (m == NULL) | | 1406 | if (m == NULL) |
1411 | return; | | 1407 | return; |
1412 | COMPATNAME(route_enqueue)(m, 0); | | 1408 | COMPATNAME(route_enqueue)(m, 0); |
1413 | #ifdef COMPAT_14 | | 1409 | #ifdef COMPAT_14 |
1414 | compat_14_rt_oifmsg(ifp); | | 1410 | compat_14_rt_oifmsg(ifp); |
1415 | #endif | | 1411 | #endif |
1416 | #ifdef COMPAT_50 | | 1412 | #ifdef COMPAT_50 |
1417 | compat_50_rt_oifmsg(ifp); | | 1413 | compat_50_rt_oifmsg(ifp); |
1418 | #endif | | 1414 | #endif |
1419 | } | | 1415 | } |
1420 | | | 1416 | |
1421 | #ifndef COMPAT_RTSOCK | | 1417 | #ifndef COMPAT_RTSOCK |
1422 | static int | | 1418 | static int |
1423 | if_addrflags(struct ifaddr *ifa) | | 1419 | if_addrflags(struct ifaddr *ifa) |
1424 | { | | 1420 | { |
1425 | | | 1421 | |
1426 | switch (ifa->ifa_addr->sa_family) { | | 1422 | switch (ifa->ifa_addr->sa_family) { |
1427 | #ifdef INET | | 1423 | #ifdef INET |
1428 | case AF_INET: | | 1424 | case AF_INET: |
1429 | return ((struct in_ifaddr *)ifa)->ia4_flags; | | 1425 | return ((struct in_ifaddr *)ifa)->ia4_flags; |
1430 | #endif | | 1426 | #endif |
1431 | #ifdef INET6 | | 1427 | #ifdef INET6 |
1432 | case AF_INET6: | | 1428 | case AF_INET6: |
1433 | return ((struct in6_ifaddr *)ifa)->ia6_flags; | | 1429 | return ((struct in6_ifaddr *)ifa)->ia6_flags; |
1434 | #endif | | 1430 | #endif |
1435 | default: | | 1431 | default: |
1436 | return 0; | | 1432 | return 0; |
1437 | } | | 1433 | } |
1438 | } | | 1434 | } |
1439 | #endif | | 1435 | #endif |
1440 | | | 1436 | |
1441 | /* | | 1437 | /* |
1442 | * This is called to generate messages from the routing socket | | 1438 | * This is called to generate messages from the routing socket |
1443 | * indicating a network interface has had addresses associated with it. | | 1439 | * indicating a network interface has had addresses associated with it. |
1444 | * if we ever reverse the logic and replace messages TO the routing | | 1440 | * if we ever reverse the logic and replace messages TO the routing |
1445 | * socket indicate a request to configure interfaces, then it will | | 1441 | * socket indicate a request to configure interfaces, then it will |
1446 | * be unnecessary as the routing socket will automatically generate | | 1442 | * be unnecessary as the routing socket will automatically generate |
1447 | * copies of it. | | 1443 | * copies of it. |
1448 | */ | | 1444 | */ |
1449 | void | | 1445 | void |
1450 | COMPATNAME(rt_newaddrmsg)(int cmd, struct ifaddr *ifa, int error, | | 1446 | COMPATNAME(rt_newaddrmsg)(int cmd, struct ifaddr *ifa, int error, |
1451 | struct rtentry *rt) | | 1447 | struct rtentry *rt) |
1452 | { | | 1448 | { |
1453 | #define cmdpass(__cmd, __pass) (((__cmd) << 2) | (__pass)) | | 1449 | #define cmdpass(__cmd, __pass) (((__cmd) << 2) | (__pass)) |
1454 | struct rt_addrinfo info; | | 1450 | struct rt_addrinfo info; |
1455 | const struct sockaddr *sa; | | 1451 | const struct sockaddr *sa; |
1456 | int pass; | | 1452 | int pass; |
1457 | struct mbuf *m; | | 1453 | struct mbuf *m; |
1458 | struct ifnet *ifp; | | 1454 | struct ifnet *ifp; |
1459 | struct rt_xmsghdr rtm; | | 1455 | struct rt_xmsghdr rtm; |
1460 | struct ifa_xmsghdr ifam; | | 1456 | struct ifa_xmsghdr ifam; |
1461 | int ncmd; | | 1457 | int ncmd; |
1462 | | | 1458 | |
1463 | KASSERT(ifa != NULL); | | 1459 | KASSERT(ifa != NULL); |
1464 | KASSERT(ifa->ifa_addr != NULL); | | 1460 | KASSERT(ifa->ifa_addr != NULL); |
1465 | ifp = ifa->ifa_ifp; | | 1461 | ifp = ifa->ifa_ifp; |
1466 | #ifdef SCTP | | 1462 | #ifdef SCTP |
1467 | if (cmd == RTM_ADD) { | | 1463 | if (cmd == RTM_ADD) { |
1468 | sctp_add_ip_address(ifa); | | 1464 | sctp_add_ip_address(ifa); |
1469 | } else if (cmd == RTM_DELETE) { | | 1465 | } else if (cmd == RTM_DELETE) { |
1470 | sctp_delete_ip_address(ifa); | | 1466 | sctp_delete_ip_address(ifa); |
1471 | } | | 1467 | } |
1472 | #endif | | 1468 | #endif |
1473 | | | 1469 | |
1474 | COMPATCALL(rt_newaddrmsg, (cmd, ifa, error, rt)); | | 1470 | COMPATCALL(rt_newaddrmsg, (cmd, ifa, error, rt)); |
1475 | if (COMPATNAME(route_info).ri_cb.any_count == 0) | | 1471 | if (COMPATNAME(route_info).ri_cb.any_count == 0) |
1476 | return; | | 1472 | return; |
1477 | for (pass = 1; pass < 3; pass++) { | | 1473 | for (pass = 1; pass < 3; pass++) { |
1478 | memset(&info, 0, sizeof(info)); | | 1474 | memset(&info, 0, sizeof(info)); |
1479 | switch (cmdpass(cmd, pass)) { | | 1475 | switch (cmdpass(cmd, pass)) { |
1480 | case cmdpass(RTM_ADD, 1): | | 1476 | case cmdpass(RTM_ADD, 1): |
1481 | case cmdpass(RTM_CHANGE, 1): | | 1477 | case cmdpass(RTM_CHANGE, 1): |
1482 | case cmdpass(RTM_DELETE, 2): | | 1478 | case cmdpass(RTM_DELETE, 2): |
1483 | case cmdpass(RTM_NEWADDR, 1): | | 1479 | case cmdpass(RTM_NEWADDR, 1): |
1484 | case cmdpass(RTM_DELADDR, 1): | | 1480 | case cmdpass(RTM_DELADDR, 1): |
1485 | case cmdpass(RTM_CHGADDR, 1): | | 1481 | case cmdpass(RTM_CHGADDR, 1): |
1486 | switch (cmd) { | | 1482 | switch (cmd) { |
1487 | case RTM_ADD: | | 1483 | case RTM_ADD: |
1488 | ncmd = RTM_XNEWADDR; | | 1484 | ncmd = RTM_XNEWADDR; |
1489 | break; | | 1485 | break; |
1490 | case RTM_DELETE: | | 1486 | case RTM_DELETE: |
1491 | ncmd = RTM_XDELADDR; | | 1487 | ncmd = RTM_XDELADDR; |
1492 | break; | | 1488 | break; |
1493 | case RTM_CHANGE: | | 1489 | case RTM_CHANGE: |
1494 | ncmd = RTM_XCHGADDR; | | 1490 | ncmd = RTM_XCHGADDR; |
1495 | break; | | 1491 | break; |
1496 | case RTM_NEWADDR: | | 1492 | case RTM_NEWADDR: |
1497 | ncmd = RTM_XNEWADDR; | | 1493 | ncmd = RTM_XNEWADDR; |
1498 | break; | | 1494 | break; |
1499 | case RTM_DELADDR: | | 1495 | case RTM_DELADDR: |
1500 | ncmd = RTM_XDELADDR; | | 1496 | ncmd = RTM_XDELADDR; |
1501 | break; | | 1497 | break; |
1502 | case RTM_CHGADDR: | | 1498 | case RTM_CHGADDR: |
1503 | ncmd = RTM_XCHGADDR; | | 1499 | ncmd = RTM_XCHGADDR; |
1504 | break; | | 1500 | break; |
1505 | default: | | 1501 | default: |
1506 | panic("%s: unknown command %d", __func__, cmd); | | 1502 | panic("%s: unknown command %d", __func__, cmd); |
1507 | } | | 1503 | } |
1508 | #ifdef COMPAT_70 | | 1504 | #ifdef COMPAT_70 |
1509 | compat_70_rt_newaddrmsg1(ncmd, ifa); | | 1505 | compat_70_rt_newaddrmsg1(ncmd, ifa); |
1510 | #endif | | 1506 | #endif |
1511 | info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr; | | 1507 | info.rti_info[RTAX_IFA] = sa = ifa->ifa_addr; |
1512 | KASSERT(ifp->if_dl != NULL); | | 1508 | KASSERT(ifp->if_dl != NULL); |
1513 | info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; | | 1509 | info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; |
1514 | info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; | | 1510 | info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; |
1515 | info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; | | 1511 | info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; |
1516 | memset(&ifam, 0, sizeof(ifam)); | | 1512 | memset(&ifam, 0, sizeof(ifam)); |
1517 | ifam.ifam_index = ifp->if_index; | | 1513 | ifam.ifam_index = ifp->if_index; |
1518 | ifam.ifam_metric = ifa->ifa_metric; | | 1514 | ifam.ifam_metric = ifa->ifa_metric; |
1519 | ifam.ifam_flags = ifa->ifa_flags; | | 1515 | ifam.ifam_flags = ifa->ifa_flags; |
1520 | #ifndef COMPAT_RTSOCK | | 1516 | #ifndef COMPAT_RTSOCK |
1521 | ifam.ifam_pid = curproc->p_pid; | | 1517 | ifam.ifam_pid = curproc->p_pid; |
1522 | ifam.ifam_addrflags = if_addrflags(ifa); | | 1518 | ifam.ifam_addrflags = if_addrflags(ifa); |
1523 | #endif | | 1519 | #endif |
1524 | m = COMPATNAME(rt_msg1)(ncmd, &info, &ifam, sizeof(ifam)); | | 1520 | m = COMPATNAME(rt_msg1)(ncmd, &info, &ifam, sizeof(ifam)); |
1525 | if (m == NULL) | | 1521 | if (m == NULL) |
1526 | continue; | | 1522 | continue; |
1527 | mtod(m, struct ifa_xmsghdr *)->ifam_addrs = | | 1523 | mtod(m, struct ifa_xmsghdr *)->ifam_addrs = |
1528 | info.rti_addrs; | | 1524 | info.rti_addrs; |
1529 | break; | | 1525 | break; |
1530 | case cmdpass(RTM_ADD, 2): | | 1526 | case cmdpass(RTM_ADD, 2): |
1531 | case cmdpass(RTM_CHANGE, 2): | | 1527 | case cmdpass(RTM_CHANGE, 2): |
1532 | case cmdpass(RTM_DELETE, 1): | | 1528 | case cmdpass(RTM_DELETE, 1): |
1533 | if (rt == NULL) | | 1529 | if (rt == NULL) |
1534 | continue; | | 1530 | continue; |
1535 | info.rti_info[RTAX_NETMASK] = rt_mask(rt); | | 1531 | info.rti_info[RTAX_NETMASK] = rt_mask(rt); |
1536 | info.rti_info[RTAX_DST] = sa = rt_getkey(rt); | | 1532 | info.rti_info[RTAX_DST] = sa = rt_getkey(rt); |
1537 | info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; | | 1533 | info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; |
1538 | memset(&rtm, 0, sizeof(rtm)); | | 1534 | memset(&rtm, 0, sizeof(rtm)); |
1539 | rtm.rtm_pid = curproc->p_pid; | | 1535 | rtm.rtm_pid = curproc->p_pid; |
1540 | rtm.rtm_index = ifp->if_index; | | 1536 | rtm.rtm_index = ifp->if_index; |
1541 | rtm.rtm_flags |= rt->rt_flags; | | 1537 | rtm.rtm_flags |= rt->rt_flags; |
1542 | rtm.rtm_errno = error; | | 1538 | rtm.rtm_errno = error; |
1543 | m = COMPATNAME(rt_msg1)(cmd, &info, &rtm, sizeof(rtm)); | | 1539 | m = COMPATNAME(rt_msg1)(cmd, &info, &rtm, sizeof(rtm)); |
1544 | if (m == NULL) | | 1540 | if (m == NULL) |
1545 | continue; | | 1541 | continue; |
1546 | mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs; | | 1542 | mtod(m, struct rt_xmsghdr *)->rtm_addrs = info.rti_addrs; |
1547 | break; | | 1543 | break; |
1548 | default: | | 1544 | default: |
1549 | continue; | | 1545 | continue; |
1550 | } | | 1546 | } |
1551 | KASSERTMSG(m != NULL, "called with wrong command"); | | 1547 | KASSERTMSG(m != NULL, "called with wrong command"); |
1552 | COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0); | | 1548 | COMPATNAME(route_enqueue)(m, sa ? sa->sa_family : 0); |
1553 | } | | 1549 | } |
1554 | #undef cmdpass | | 1550 | #undef cmdpass |
1555 | | | 1551 | |
1556 | } | | 1552 | } |
1557 | | | 1553 | |
1558 | static struct mbuf * | | 1554 | static struct mbuf * |
1559 | rt_makeifannouncemsg(struct ifnet *ifp, int type, int what, | | 1555 | rt_makeifannouncemsg(struct ifnet *ifp, int type, int what, |
1560 | struct rt_addrinfo *info) | | 1556 | struct rt_addrinfo *info) |
1561 | { | | 1557 | { |
1562 | struct if_xannouncemsghdr ifan; | | 1558 | struct if_xannouncemsghdr ifan; |
1563 | | | 1559 | |
1564 | memset(info, 0, sizeof(*info)); | | 1560 | memset(info, 0, sizeof(*info)); |
1565 | memset(&ifan, 0, sizeof(ifan)); | | 1561 | memset(&ifan, 0, sizeof(ifan)); |
1566 | ifan.ifan_index = ifp->if_index; | | 1562 | ifan.ifan_index = ifp->if_index; |
1567 | strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name)); | | 1563 | strlcpy(ifan.ifan_name, ifp->if_xname, sizeof(ifan.ifan_name)); |
1568 | ifan.ifan_what = what; | | 1564 | ifan.ifan_what = what; |
1569 | return COMPATNAME(rt_msg1)(type, info, &ifan, sizeof(ifan)); | | 1565 | return COMPATNAME(rt_msg1)(type, info, &ifan, sizeof(ifan)); |
1570 | } | | 1566 | } |
1571 | | | 1567 | |
1572 | /* | | 1568 | /* |
1573 | * This is called to generate routing socket messages indicating | | 1569 | * This is called to generate routing socket messages indicating |