| @@ -1,1677 +1,1711 @@ | | | @@ -1,1677 +1,1711 @@ |
1 | /* $NetBSD: if_arp.c,v 1.151 2011/05/03 16:00:29 dyoung Exp $ */ | | 1 | /* $NetBSD: if_arp.c,v 1.152 2011/08/27 09:05:54 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Public Access Networks Corporation ("Panix"). It was developed under | | 8 | * by Public Access Networks Corporation ("Panix"). It was developed under |
9 | * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. | | 9 | * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. | | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright | | 16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the | | 17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. | | 18 | * documentation and/or other materials provided with the distribution. |
19 | * | | 19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * Copyright (c) 1982, 1986, 1988, 1993 | | 34 | * Copyright (c) 1982, 1986, 1988, 1993 |
35 | * The Regents of the University of California. All rights reserved. | | 35 | * The Regents of the University of California. All rights reserved. |
36 | * | | 36 | * |
37 | * Redistribution and use in source and binary forms, with or without | | 37 | * Redistribution and use in source and binary forms, with or without |
38 | * modification, are permitted provided that the following conditions | | 38 | * modification, are permitted provided that the following conditions |
39 | * are met: | | 39 | * are met: |
40 | * 1. Redistributions of source code must retain the above copyright | | 40 | * 1. Redistributions of source code must retain the above copyright |
41 | * notice, this list of conditions and the following disclaimer. | | 41 | * notice, this list of conditions and the following disclaimer. |
42 | * 2. Redistributions in binary form must reproduce the above copyright | | 42 | * 2. Redistributions in binary form must reproduce the above copyright |
43 | * notice, this list of conditions and the following disclaimer in the | | 43 | * notice, this list of conditions and the following disclaimer in the |
44 | * documentation and/or other materials provided with the distribution. | | 44 | * documentation and/or other materials provided with the distribution. |
45 | * 3. Neither the name of the University nor the names of its contributors | | 45 | * 3. Neither the name of the University nor the names of its contributors |
46 | * may be used to endorse or promote products derived from this software | | 46 | * may be used to endorse or promote products derived from this software |
47 | * without specific prior written permission. | | 47 | * without specific prior written permission. |
48 | * | | 48 | * |
49 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 49 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
50 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 50 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
51 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 51 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
59 | * SUCH DAMAGE. | | 59 | * SUCH DAMAGE. |
60 | * | | 60 | * |
61 | * @(#)if_ether.c 8.2 (Berkeley) 9/26/94 | | 61 | * @(#)if_ether.c 8.2 (Berkeley) 9/26/94 |
62 | */ | | 62 | */ |
63 | | | 63 | |
64 | /* | | 64 | /* |
65 | * Ethernet address resolution protocol. | | 65 | * Ethernet address resolution protocol. |
66 | * TODO: | | 66 | * TODO: |
67 | * add "inuse/lock" bit (or ref. count) along with valid bit | | 67 | * add "inuse/lock" bit (or ref. count) along with valid bit |
68 | */ | | 68 | */ |
69 | | | 69 | |
70 | #include <sys/cdefs.h> | | 70 | #include <sys/cdefs.h> |
71 | __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.151 2011/05/03 16:00:29 dyoung Exp $"); | | 71 | __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.152 2011/08/27 09:05:54 christos Exp $"); |
72 | | | 72 | |
73 | #include "opt_ddb.h" | | 73 | #include "opt_ddb.h" |
74 | #include "opt_inet.h" | | 74 | #include "opt_inet.h" |
75 | | | 75 | |
76 | #ifdef INET | | 76 | #ifdef INET |
77 | | | 77 | |
78 | #include "bridge.h" | | 78 | #include "bridge.h" |
79 | | | 79 | |
80 | #include <sys/param.h> | | 80 | #include <sys/param.h> |
81 | #include <sys/systm.h> | | 81 | #include <sys/systm.h> |
82 | #include <sys/callout.h> | | 82 | #include <sys/callout.h> |
83 | #include <sys/malloc.h> | | 83 | #include <sys/malloc.h> |
84 | #include <sys/mbuf.h> | | 84 | #include <sys/mbuf.h> |
85 | #include <sys/socket.h> | | 85 | #include <sys/socket.h> |
86 | #include <sys/time.h> | | 86 | #include <sys/time.h> |
87 | #include <sys/timetc.h> | | 87 | #include <sys/timetc.h> |
88 | #include <sys/kernel.h> | | 88 | #include <sys/kernel.h> |
89 | #include <sys/errno.h> | | 89 | #include <sys/errno.h> |
90 | #include <sys/ioctl.h> | | 90 | #include <sys/ioctl.h> |
91 | #include <sys/syslog.h> | | 91 | #include <sys/syslog.h> |
92 | #include <sys/proc.h> | | 92 | #include <sys/proc.h> |
93 | #include <sys/protosw.h> | | 93 | #include <sys/protosw.h> |
94 | #include <sys/domain.h> | | 94 | #include <sys/domain.h> |
95 | #include <sys/sysctl.h> | | 95 | #include <sys/sysctl.h> |
96 | #include <sys/socketvar.h> | | 96 | #include <sys/socketvar.h> |
97 | #include <sys/percpu.h> | | 97 | #include <sys/percpu.h> |
98 | | | 98 | |
99 | #include <net/ethertypes.h> | | 99 | #include <net/ethertypes.h> |
100 | #include <net/if.h> | | 100 | #include <net/if.h> |
101 | #include <net/if_dl.h> | | 101 | #include <net/if_dl.h> |
102 | #include <net/if_token.h> | | 102 | #include <net/if_token.h> |
103 | #include <net/if_types.h> | | 103 | #include <net/if_types.h> |
104 | #include <net/if_ether.h> | | 104 | #include <net/if_ether.h> |
105 | #include <net/route.h> | | 105 | #include <net/route.h> |
106 | #include <net/net_stats.h> | | 106 | #include <net/net_stats.h> |
107 | | | 107 | |
108 | #include <netinet/in.h> | | 108 | #include <netinet/in.h> |
109 | #include <netinet/in_systm.h> | | 109 | #include <netinet/in_systm.h> |
110 | #include <netinet/in_var.h> | | 110 | #include <netinet/in_var.h> |
111 | #include <netinet/ip.h> | | 111 | #include <netinet/ip.h> |
112 | #include <netinet/if_inarp.h> | | 112 | #include <netinet/if_inarp.h> |
113 | | | 113 | |
114 | #include "arcnet.h" | | 114 | #include "arcnet.h" |
115 | #if NARCNET > 0 | | 115 | #if NARCNET > 0 |
116 | #include <net/if_arc.h> | | 116 | #include <net/if_arc.h> |
117 | #endif | | 117 | #endif |
118 | #include "fddi.h" | | 118 | #include "fddi.h" |
119 | #if NFDDI > 0 | | 119 | #if NFDDI > 0 |
120 | #include <net/if_fddi.h> | | 120 | #include <net/if_fddi.h> |
121 | #endif | | 121 | #endif |
122 | #include "token.h" | | 122 | #include "token.h" |
123 | #include "carp.h" | | 123 | #include "carp.h" |
124 | #if NCARP > 0 | | 124 | #if NCARP > 0 |
125 | #include <netinet/ip_carp.h> | | 125 | #include <netinet/ip_carp.h> |
126 | #endif | | 126 | #endif |
127 | | | 127 | |
128 | #define SIN(s) ((struct sockaddr_in *)s) | | 128 | #define SIN(s) ((struct sockaddr_in *)s) |
129 | #define SRP(s) ((struct sockaddr_inarp *)s) | | 129 | #define SRP(s) ((struct sockaddr_inarp *)s) |
130 | | | 130 | |
131 | /* | | 131 | /* |
132 | * ARP trailer negotiation. Trailer protocol is not IP specific, | | 132 | * ARP trailer negotiation. Trailer protocol is not IP specific, |
133 | * but ARP request/response use IP addresses. | | 133 | * but ARP request/response use IP addresses. |
134 | */ | | 134 | */ |
135 | #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL | | 135 | #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL |
136 | | | 136 | |
137 | /* timer values */ | | 137 | /* timer values */ |
138 | int arpt_prune = (5*60*1); /* walk list every 5 minutes */ | | 138 | int arpt_prune = (5*60*1); /* walk list every 5 minutes */ |
139 | int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ | | 139 | int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ |
140 | int arpt_down = 20; /* once declared down, don't send for 20 secs */ | | 140 | int arpt_down = 20; /* once declared down, don't send for 20 secs */ |
141 | int arpt_refresh = (5*60); /* time left before refreshing */ | | 141 | int arpt_refresh = (5*60); /* time left before refreshing */ |
142 | #define rt_expire rt_rmx.rmx_expire | | 142 | #define rt_expire rt_rmx.rmx_expire |
143 | #define rt_pksent rt_rmx.rmx_pksent | | 143 | #define rt_pksent rt_rmx.rmx_pksent |
144 | | | 144 | |
145 | static struct sockaddr *arp_setgate(struct rtentry *, struct sockaddr *, | | 145 | static struct sockaddr *arp_setgate(struct rtentry *, struct sockaddr *, |
146 | const struct sockaddr *); | | 146 | const struct sockaddr *); |
147 | static void arptfree(struct llinfo_arp *); | | 147 | static void arptfree(struct llinfo_arp *); |
148 | static void arptimer(void *); | | 148 | static void arptimer(void *); |
149 | static struct llinfo_arp *arplookup1(struct mbuf *, const struct in_addr *, | | 149 | static struct llinfo_arp *arplookup1(struct mbuf *, const struct in_addr *, |
150 | int, int, struct rtentry *); | | 150 | int, int, struct rtentry *); |
151 | static struct llinfo_arp *arplookup(struct mbuf *, const struct in_addr *, | | 151 | static struct llinfo_arp *arplookup(struct mbuf *, const struct in_addr *, |
152 | int, int); | | 152 | int, int); |
153 | static void in_arpinput(struct mbuf *); | | 153 | static void in_arpinput(struct mbuf *); |
154 | static void arp_drainstub(void); | | 154 | static void arp_drainstub(void); |
155 | | | 155 | |
156 | LIST_HEAD(, llinfo_arp) llinfo_arp; | | 156 | LIST_HEAD(, llinfo_arp) llinfo_arp; |
157 | struct ifqueue arpintrq = { | | 157 | struct ifqueue arpintrq = { |
158 | .ifq_head = NULL, | | 158 | .ifq_head = NULL, |
159 | .ifq_tail = NULL, | | 159 | .ifq_tail = NULL, |
160 | .ifq_len = 0, | | 160 | .ifq_len = 0, |
161 | .ifq_maxlen = 50, | | 161 | .ifq_maxlen = 50, |
162 | .ifq_drops = 0, | | 162 | .ifq_drops = 0, |
163 | }; | | 163 | }; |
164 | int arp_inuse, arp_allocated, arp_intimer; | | 164 | int arp_inuse, arp_allocated, arp_intimer; |
165 | int arp_maxtries = 5; | | 165 | int arp_maxtries = 5; |
166 | int useloopback = 1; /* use loopback interface for local traffic */ | | 166 | int useloopback = 1; /* use loopback interface for local traffic */ |
167 | int arpinit_done = 0; | | 167 | int arpinit_done = 0; |
168 | | | 168 | |
169 | static percpu_t *arpstat_percpu; | | 169 | static percpu_t *arpstat_percpu; |
170 | | | 170 | |
171 | #define ARP_STAT_GETREF() _NET_STAT_GETREF(arpstat_percpu) | | 171 | #define ARP_STAT_GETREF() _NET_STAT_GETREF(arpstat_percpu) |
172 | #define ARP_STAT_PUTREF() _NET_STAT_PUTREF(arpstat_percpu) | | 172 | #define ARP_STAT_PUTREF() _NET_STAT_PUTREF(arpstat_percpu) |
173 | | | 173 | |
174 | #define ARP_STATINC(x) _NET_STATINC(arpstat_percpu, x) | | 174 | #define ARP_STATINC(x) _NET_STATINC(arpstat_percpu, x) |
175 | #define ARP_STATADD(x, v) _NET_STATADD(arpstat_percpu, x, v) | | 175 | #define ARP_STATADD(x, v) _NET_STATADD(arpstat_percpu, x, v) |
176 | | | 176 | |
177 | struct callout arptimer_ch; | | 177 | struct callout arptimer_ch; |
178 | | | 178 | |
179 | /* revarp state */ | | 179 | /* revarp state */ |
180 | struct in_addr myip, srv_ip; | | 180 | struct in_addr myip, srv_ip; |
181 | int myip_initialized = 0; | | 181 | int myip_initialized = 0; |
182 | int revarp_in_progress = 0; | | 182 | int revarp_in_progress = 0; |
183 | struct ifnet *myip_ifp = NULL; | | 183 | struct ifnet *myip_ifp = NULL; |
184 | | | 184 | |
185 | #ifdef DDB | | 185 | #ifdef DDB |
186 | static void db_print_sa(const struct sockaddr *); | | 186 | static void db_print_sa(const struct sockaddr *); |
187 | static void db_print_ifa(struct ifaddr *); | | 187 | static void db_print_ifa(struct ifaddr *); |
188 | static void db_print_llinfo(void *); | | 188 | static void db_print_llinfo(void *); |
189 | static int db_show_rtentry(struct rtentry *, void *); | | 189 | static int db_show_rtentry(struct rtentry *, void *); |
190 | #endif | | 190 | #endif |
191 | | | 191 | |
192 | static int arp_drainwanted; | | 192 | static int arp_drainwanted; |
193 | | | 193 | |
| | | 194 | static int log_movements = 1; |
| | | 195 | static int log_permanent_modify = 1; |
| | | 196 | static int log_wrong_iface = 1; |
| | | 197 | |
194 | /* | | 198 | /* |
195 | * this should be elsewhere. | | 199 | * this should be elsewhere. |
196 | */ | | 200 | */ |
197 | | | 201 | |
198 | static char * | | 202 | static char * |
199 | lla_snprintf(u_int8_t *, int); | | 203 | lla_snprintf(u_int8_t *, int); |
200 | | | 204 | |
201 | static char * | | 205 | static char * |
202 | lla_snprintf(u_int8_t *adrp, int len) | | 206 | lla_snprintf(u_int8_t *adrp, int len) |
203 | { | | 207 | { |
204 | #define NUMBUFS 3 | | 208 | #define NUMBUFS 3 |
205 | static char buf[NUMBUFS][16*3]; | | 209 | static char buf[NUMBUFS][16*3]; |
206 | static int bnum = 0; | | 210 | static int bnum = 0; |
207 | | | 211 | |
208 | int i; | | 212 | int i; |
209 | char *p; | | 213 | char *p; |
210 | | | 214 | |
211 | p = buf[bnum]; | | 215 | p = buf[bnum]; |
212 | | | 216 | |
213 | *p++ = hexdigits[(*adrp)>>4]; | | 217 | *p++ = hexdigits[(*adrp)>>4]; |
214 | *p++ = hexdigits[(*adrp++)&0xf]; | | 218 | *p++ = hexdigits[(*adrp++)&0xf]; |
215 | | | 219 | |
216 | for (i=1; i<len && i<16; i++) { | | 220 | for (i=1; i<len && i<16; i++) { |
217 | *p++ = ':'; | | 221 | *p++ = ':'; |
218 | *p++ = hexdigits[(*adrp)>>4]; | | 222 | *p++ = hexdigits[(*adrp)>>4]; |
219 | *p++ = hexdigits[(*adrp++)&0xf]; | | 223 | *p++ = hexdigits[(*adrp++)&0xf]; |
220 | } | | 224 | } |
221 | | | 225 | |
222 | *p = 0; | | 226 | *p = 0; |
223 | p = buf[bnum]; | | 227 | p = buf[bnum]; |
224 | bnum = (bnum + 1) % NUMBUFS; | | 228 | bnum = (bnum + 1) % NUMBUFS; |
225 | return p; | | 229 | return p; |
226 | } | | 230 | } |
227 | | | 231 | |
228 | DOMAIN_DEFINE(arpdomain); /* forward declare and add to link set */ | | 232 | DOMAIN_DEFINE(arpdomain); /* forward declare and add to link set */ |
229 | | | 233 | |
230 | static void | | 234 | static void |
231 | arp_fasttimo(void) | | 235 | arp_fasttimo(void) |
232 | { | | 236 | { |
233 | if (arp_drainwanted) { | | 237 | if (arp_drainwanted) { |
234 | arp_drain(); | | 238 | arp_drain(); |
235 | arp_drainwanted = 0; | | 239 | arp_drainwanted = 0; |
236 | } | | 240 | } |
237 | } | | 241 | } |
238 | | | 242 | |
239 | const struct protosw arpsw[] = { | | 243 | const struct protosw arpsw[] = { |
240 | { .pr_type = 0, | | 244 | { .pr_type = 0, |
241 | .pr_domain = &arpdomain, | | 245 | .pr_domain = &arpdomain, |
242 | .pr_protocol = 0, | | 246 | .pr_protocol = 0, |
243 | .pr_flags = 0, | | 247 | .pr_flags = 0, |
244 | .pr_input = 0, | | 248 | .pr_input = 0, |
245 | .pr_output = 0, | | 249 | .pr_output = 0, |
246 | .pr_ctlinput = 0, | | 250 | .pr_ctlinput = 0, |
247 | .pr_ctloutput = 0, | | 251 | .pr_ctloutput = 0, |
248 | .pr_usrreq = 0, | | 252 | .pr_usrreq = 0, |
249 | .pr_init = arp_init, | | 253 | .pr_init = arp_init, |
250 | .pr_fasttimo = arp_fasttimo, | | 254 | .pr_fasttimo = arp_fasttimo, |
251 | .pr_slowtimo = 0, | | 255 | .pr_slowtimo = 0, |
252 | .pr_drain = arp_drainstub, | | 256 | .pr_drain = arp_drainstub, |
253 | } | | 257 | } |
254 | }; | | 258 | }; |
255 | | | 259 | |
256 | | | 260 | |
257 | struct domain arpdomain = { | | 261 | struct domain arpdomain = { |
258 | .dom_family = PF_ARP, | | 262 | .dom_family = PF_ARP, |
259 | .dom_name = "arp", | | 263 | .dom_name = "arp", |
260 | .dom_protosw = arpsw, | | 264 | .dom_protosw = arpsw, |
261 | .dom_protoswNPROTOSW = &arpsw[__arraycount(arpsw)], | | 265 | .dom_protoswNPROTOSW = &arpsw[__arraycount(arpsw)], |
262 | }; | | 266 | }; |
263 | | | 267 | |
264 | /* | | 268 | /* |
265 | * ARP table locking. | | 269 | * ARP table locking. |
266 | * | | 270 | * |
267 | * to prevent lossage vs. the arp_drain routine (which may be called at | | 271 | * to prevent lossage vs. the arp_drain routine (which may be called at |
268 | * any time, including in a device driver context), we do two things: | | 272 | * any time, including in a device driver context), we do two things: |
269 | * | | 273 | * |
270 | * 1) manipulation of la->la_hold is done at splnet() (for all of | | 274 | * 1) manipulation of la->la_hold is done at splnet() (for all of |
271 | * about two instructions). | | 275 | * about two instructions). |
272 | * | | 276 | * |
273 | * 2) manipulation of the arp table's linked list is done under the | | 277 | * 2) manipulation of the arp table's linked list is done under the |
274 | * protection of the ARP_LOCK; if arp_drain() or arptimer is called | | 278 | * protection of the ARP_LOCK; if arp_drain() or arptimer is called |
275 | * while the arp table is locked, we punt and try again later. | | 279 | * while the arp table is locked, we punt and try again later. |
276 | */ | | 280 | */ |
277 | | | 281 | |
278 | static int arp_locked; | | 282 | static int arp_locked; |
279 | static inline int arp_lock_try(int); | | 283 | static inline int arp_lock_try(int); |
280 | static inline void arp_unlock(void); | | 284 | static inline void arp_unlock(void); |
281 | | | 285 | |
282 | static inline int | | 286 | static inline int |
283 | arp_lock_try(int recurse) | | 287 | arp_lock_try(int recurse) |
284 | { | | 288 | { |
285 | int s; | | 289 | int s; |
286 | | | 290 | |
287 | /* | | 291 | /* |
288 | * Use splvm() -- we're blocking things that would cause | | 292 | * Use splvm() -- we're blocking things that would cause |
289 | * mbuf allocation. | | 293 | * mbuf allocation. |
290 | */ | | 294 | */ |
291 | s = splvm(); | | 295 | s = splvm(); |
292 | if (!recurse && arp_locked) { | | 296 | if (!recurse && arp_locked) { |
293 | splx(s); | | 297 | splx(s); |
294 | return 0; | | 298 | return 0; |
295 | } | | 299 | } |
296 | arp_locked++; | | 300 | arp_locked++; |
297 | splx(s); | | 301 | splx(s); |
298 | return 1; | | 302 | return 1; |
299 | } | | 303 | } |
300 | | | 304 | |
301 | static inline void | | 305 | static inline void |
302 | arp_unlock(void) | | 306 | arp_unlock(void) |
303 | { | | 307 | { |
304 | int s; | | 308 | int s; |
305 | | | 309 | |
306 | s = splvm(); | | 310 | s = splvm(); |
307 | arp_locked--; | | 311 | arp_locked--; |
308 | splx(s); | | 312 | splx(s); |
309 | } | | 313 | } |
310 | | | 314 | |
311 | #ifdef DIAGNOSTIC | | 315 | #ifdef DIAGNOSTIC |
312 | #define ARP_LOCK(recurse) \ | | 316 | #define ARP_LOCK(recurse) \ |
313 | do { \ | | 317 | do { \ |
314 | if (arp_lock_try(recurse) == 0) { \ | | 318 | if (arp_lock_try(recurse) == 0) { \ |
315 | printf("%s:%d: arp already locked\n", __FILE__, __LINE__); \ | | 319 | printf("%s:%d: arp already locked\n", __FILE__, __LINE__); \ |
316 | panic("arp_lock"); \ | | 320 | panic("arp_lock"); \ |
317 | } \ | | 321 | } \ |
318 | } while (/*CONSTCOND*/ 0) | | 322 | } while (/*CONSTCOND*/ 0) |
319 | #define ARP_LOCK_CHECK() \ | | 323 | #define ARP_LOCK_CHECK() \ |
320 | do { \ | | 324 | do { \ |
321 | if (arp_locked == 0) { \ | | 325 | if (arp_locked == 0) { \ |
322 | printf("%s:%d: arp lock not held\n", __FILE__, __LINE__); \ | | 326 | printf("%s:%d: arp lock not held\n", __FILE__, __LINE__); \ |
323 | panic("arp lock check"); \ | | 327 | panic("arp lock check"); \ |
324 | } \ | | 328 | } \ |
325 | } while (/*CONSTCOND*/ 0) | | 329 | } while (/*CONSTCOND*/ 0) |
326 | #else | | 330 | #else |
327 | #define ARP_LOCK(x) (void) arp_lock_try(x) | | 331 | #define ARP_LOCK(x) (void) arp_lock_try(x) |
328 | #define ARP_LOCK_CHECK() /* nothing */ | | 332 | #define ARP_LOCK_CHECK() /* nothing */ |
329 | #endif | | 333 | #endif |
330 | | | 334 | |
331 | #define ARP_UNLOCK() arp_unlock() | | 335 | #define ARP_UNLOCK() arp_unlock() |
332 | | | 336 | |
333 | static void sysctl_net_inet_arp_setup(struct sysctllog **); | | 337 | static void sysctl_net_inet_arp_setup(struct sysctllog **); |
334 | | | 338 | |
335 | void | | 339 | void |
336 | arp_init(void) | | 340 | arp_init(void) |
337 | { | | 341 | { |
338 | | | 342 | |
339 | sysctl_net_inet_arp_setup(NULL); | | 343 | sysctl_net_inet_arp_setup(NULL); |
340 | arpstat_percpu = percpu_alloc(sizeof(uint64_t) * ARP_NSTATS); | | 344 | arpstat_percpu = percpu_alloc(sizeof(uint64_t) * ARP_NSTATS); |
341 | } | | 345 | } |
342 | | | 346 | |
343 | static void | | 347 | static void |
344 | arp_drainstub(void) | | 348 | arp_drainstub(void) |
345 | { | | 349 | { |
346 | arp_drainwanted = 1; | | 350 | arp_drainwanted = 1; |
347 | } | | 351 | } |
348 | | | 352 | |
349 | /* | | 353 | /* |
350 | * ARP protocol drain routine. Called when memory is in short supply. | | 354 | * ARP protocol drain routine. Called when memory is in short supply. |
351 | * Called at splvm(); don't acquire softnet_lock as can be called from | | 355 | * Called at splvm(); don't acquire softnet_lock as can be called from |
352 | * hardware interrupt handlers. | | 356 | * hardware interrupt handlers. |
353 | */ | | 357 | */ |
354 | void | | 358 | void |
355 | arp_drain(void) | | 359 | arp_drain(void) |
356 | { | | 360 | { |
357 | struct llinfo_arp *la, *nla; | | 361 | struct llinfo_arp *la, *nla; |
358 | int count = 0; | | 362 | int count = 0; |
359 | struct mbuf *mold; | | 363 | struct mbuf *mold; |
360 | | | 364 | |
361 | KERNEL_LOCK(1, NULL); | | 365 | KERNEL_LOCK(1, NULL); |
362 | | | 366 | |
363 | if (arp_lock_try(0) == 0) { | | 367 | if (arp_lock_try(0) == 0) { |
364 | KERNEL_UNLOCK_ONE(NULL); | | 368 | KERNEL_UNLOCK_ONE(NULL); |
365 | return; | | 369 | return; |
366 | } | | 370 | } |
367 | | | 371 | |
368 | for (la = LIST_FIRST(&llinfo_arp); la != NULL; la = nla) { | | 372 | for (la = LIST_FIRST(&llinfo_arp); la != NULL; la = nla) { |
369 | nla = LIST_NEXT(la, la_list); | | 373 | nla = LIST_NEXT(la, la_list); |
370 | | | 374 | |
371 | mold = la->la_hold; | | 375 | mold = la->la_hold; |
372 | la->la_hold = 0; | | 376 | la->la_hold = 0; |
373 | | | 377 | |
374 | if (mold) { | | 378 | if (mold) { |
375 | m_freem(mold); | | 379 | m_freem(mold); |
376 | count++; | | 380 | count++; |
377 | } | | 381 | } |
378 | } | | 382 | } |
379 | ARP_UNLOCK(); | | 383 | ARP_UNLOCK(); |
380 | ARP_STATADD(ARP_STAT_DFRDROPPED, count); | | 384 | ARP_STATADD(ARP_STAT_DFRDROPPED, count); |
381 | KERNEL_UNLOCK_ONE(NULL); | | 385 | KERNEL_UNLOCK_ONE(NULL); |
382 | } | | 386 | } |
383 | | | 387 | |
384 | | | 388 | |
385 | /* | | 389 | /* |
386 | * Timeout routine. Age arp_tab entries periodically. | | 390 | * Timeout routine. Age arp_tab entries periodically. |
387 | */ | | 391 | */ |
388 | /* ARGSUSED */ | | 392 | /* ARGSUSED */ |
389 | static void | | 393 | static void |
390 | arptimer(void *arg) | | 394 | arptimer(void *arg) |
391 | { | | 395 | { |
392 | struct llinfo_arp *la, *nla; | | 396 | struct llinfo_arp *la, *nla; |
393 | | | 397 | |
394 | mutex_enter(softnet_lock); | | 398 | mutex_enter(softnet_lock); |
395 | KERNEL_LOCK(1, NULL); | | 399 | KERNEL_LOCK(1, NULL); |
396 | | | 400 | |
397 | if (arp_lock_try(0) == 0) { | | 401 | if (arp_lock_try(0) == 0) { |
398 | /* get it later.. */ | | 402 | /* get it later.. */ |
399 | KERNEL_UNLOCK_ONE(NULL); | | 403 | KERNEL_UNLOCK_ONE(NULL); |
400 | mutex_exit(softnet_lock); | | 404 | mutex_exit(softnet_lock); |
401 | return; | | 405 | return; |
402 | } | | 406 | } |
403 | | | 407 | |
404 | callout_reset(&arptimer_ch, arpt_prune * hz, arptimer, NULL); | | 408 | callout_reset(&arptimer_ch, arpt_prune * hz, arptimer, NULL); |
405 | for (la = LIST_FIRST(&llinfo_arp); la != NULL; la = nla) { | | 409 | for (la = LIST_FIRST(&llinfo_arp); la != NULL; la = nla) { |
406 | struct rtentry *rt = la->la_rt; | | 410 | struct rtentry *rt = la->la_rt; |
407 | | | 411 | |
408 | nla = LIST_NEXT(la, la_list); | | 412 | nla = LIST_NEXT(la, la_list); |
409 | if (rt->rt_expire == 0) | | 413 | if (rt->rt_expire == 0) |
410 | continue; | | 414 | continue; |
411 | if ((rt->rt_expire - time_second) < arpt_refresh && | | 415 | if ((rt->rt_expire - time_second) < arpt_refresh && |
412 | rt->rt_pksent > (time_second - arpt_keep)) { | | 416 | rt->rt_pksent > (time_second - arpt_keep)) { |
413 | /* | | 417 | /* |
414 | * If the entry has been used during since last | | 418 | * If the entry has been used during since last |
415 | * refresh, try to renew it before deleting. | | 419 | * refresh, try to renew it before deleting. |
416 | */ | | 420 | */ |
417 | arprequest(rt->rt_ifp, | | 421 | arprequest(rt->rt_ifp, |
418 | &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, | | 422 | &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, |
419 | &satocsin(rt_getkey(rt))->sin_addr, | | 423 | &satocsin(rt_getkey(rt))->sin_addr, |
420 | CLLADDR(rt->rt_ifp->if_sadl)); | | 424 | CLLADDR(rt->rt_ifp->if_sadl)); |
421 | } else if (rt->rt_expire <= time_second) | | 425 | } else if (rt->rt_expire <= time_second) |
422 | arptfree(la); /* timer has expired; clear */ | | 426 | arptfree(la); /* timer has expired; clear */ |
423 | } | | 427 | } |
424 | | | 428 | |
425 | ARP_UNLOCK(); | | 429 | ARP_UNLOCK(); |
426 | | | 430 | |
427 | KERNEL_UNLOCK_ONE(NULL); | | 431 | KERNEL_UNLOCK_ONE(NULL); |
428 | mutex_exit(softnet_lock); | | 432 | mutex_exit(softnet_lock); |
429 | } | | 433 | } |
430 | | | 434 | |
431 | /* | | 435 | /* |
432 | * We set the gateway for RTF_CLONING routes to a "prototype" | | 436 | * We set the gateway for RTF_CLONING routes to a "prototype" |
433 | * link-layer sockaddr whose interface type (if_type) and interface | | 437 | * link-layer sockaddr whose interface type (if_type) and interface |
434 | * index (if_index) fields are prepared. | | 438 | * index (if_index) fields are prepared. |
435 | */ | | 439 | */ |
436 | static struct sockaddr * | | 440 | static struct sockaddr * |
437 | arp_setgate(struct rtentry *rt, struct sockaddr *gate, | | 441 | arp_setgate(struct rtentry *rt, struct sockaddr *gate, |
438 | const struct sockaddr *netmask) | | 442 | const struct sockaddr *netmask) |
439 | { | | 443 | { |
440 | const struct ifnet *ifp = rt->rt_ifp; | | 444 | const struct ifnet *ifp = rt->rt_ifp; |
441 | uint8_t namelen = strlen(ifp->if_xname); | | 445 | uint8_t namelen = strlen(ifp->if_xname); |
442 | uint8_t addrlen = ifp->if_addrlen; | | 446 | uint8_t addrlen = ifp->if_addrlen; |
443 | | | 447 | |
444 | /* | | 448 | /* |
445 | * XXX: If this is a manually added route to interface | | 449 | * XXX: If this is a manually added route to interface |
446 | * such as older version of routed or gated might provide, | | 450 | * such as older version of routed or gated might provide, |
447 | * restore cloning bit. | | 451 | * restore cloning bit. |
448 | */ | | 452 | */ |
449 | if ((rt->rt_flags & RTF_HOST) == 0 && netmask != NULL && | | 453 | if ((rt->rt_flags & RTF_HOST) == 0 && netmask != NULL && |
450 | satocsin(netmask)->sin_addr.s_addr != 0xffffffff) | | 454 | satocsin(netmask)->sin_addr.s_addr != 0xffffffff) |
451 | rt->rt_flags |= RTF_CLONING; | | 455 | rt->rt_flags |= RTF_CLONING; |
452 | if (rt->rt_flags & RTF_CLONING) { | | 456 | if (rt->rt_flags & RTF_CLONING) { |
453 | union { | | 457 | union { |
454 | struct sockaddr sa; | | 458 | struct sockaddr sa; |
455 | struct sockaddr_storage ss; | | 459 | struct sockaddr_storage ss; |
456 | struct sockaddr_dl sdl; | | 460 | struct sockaddr_dl sdl; |
457 | } u; | | 461 | } u; |
458 | /* | | 462 | /* |
459 | * Case 1: This route should come from a route to iface. | | 463 | * Case 1: This route should come from a route to iface. |
460 | */ | | 464 | */ |
461 | sockaddr_dl_init(&u.sdl, sizeof(u.ss), | | 465 | sockaddr_dl_init(&u.sdl, sizeof(u.ss), |
462 | ifp->if_index, ifp->if_type, NULL, namelen, NULL, addrlen); | | 466 | ifp->if_index, ifp->if_type, NULL, namelen, NULL, addrlen); |
463 | rt_setgate(rt, &u.sa); | | 467 | rt_setgate(rt, &u.sa); |
464 | gate = rt->rt_gateway; | | 468 | gate = rt->rt_gateway; |
465 | } | | 469 | } |
466 | return gate; | | 470 | return gate; |
467 | } | | 471 | } |
468 | | | 472 | |
469 | /* | | 473 | /* |
470 | * Parallel to llc_rtrequest. | | 474 | * Parallel to llc_rtrequest. |
471 | */ | | 475 | */ |
472 | void | | 476 | void |
473 | arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info) | | 477 | arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info) |
474 | { | | 478 | { |
475 | struct sockaddr *gate = rt->rt_gateway; | | 479 | struct sockaddr *gate = rt->rt_gateway; |
476 | struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; | | 480 | struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo; |
477 | size_t allocsize; | | 481 | size_t allocsize; |
478 | struct mbuf *mold; | | 482 | struct mbuf *mold; |
479 | int s; | | 483 | int s; |
480 | struct in_ifaddr *ia; | | 484 | struct in_ifaddr *ia; |
481 | struct ifaddr *ifa; | | 485 | struct ifaddr *ifa; |
482 | struct ifnet *ifp = rt->rt_ifp; | | 486 | struct ifnet *ifp = rt->rt_ifp; |
483 | | | 487 | |
484 | if (!arpinit_done) { | | 488 | if (!arpinit_done) { |
485 | arpinit_done = 1; | | 489 | arpinit_done = 1; |
486 | /* | | 490 | /* |
487 | * We generate expiration times from time_second | | 491 | * We generate expiration times from time_second |
488 | * so avoid accidentally creating permanent routes. | | 492 | * so avoid accidentally creating permanent routes. |
489 | */ | | 493 | */ |
490 | if (time_second == 0) { | | 494 | if (time_second == 0) { |
491 | struct timespec ts; | | 495 | struct timespec ts; |
492 | ts.tv_sec = 1; | | 496 | ts.tv_sec = 1; |
493 | ts.tv_nsec = 0; | | 497 | ts.tv_nsec = 0; |
494 | tc_setclock(&ts); | | 498 | tc_setclock(&ts); |
495 | } | | 499 | } |
496 | callout_init(&arptimer_ch, CALLOUT_MPSAFE); | | 500 | callout_init(&arptimer_ch, CALLOUT_MPSAFE); |
497 | callout_reset(&arptimer_ch, hz, arptimer, NULL); | | 501 | callout_reset(&arptimer_ch, hz, arptimer, NULL); |
498 | } | | 502 | } |
499 | | | 503 | |
500 | if (req == RTM_LLINFO_UPD) { | | 504 | if (req == RTM_LLINFO_UPD) { |
501 | struct in_addr *in; | | 505 | struct in_addr *in; |
502 | | | 506 | |
503 | if ((ifa = info->rti_ifa) == NULL) | | 507 | if ((ifa = info->rti_ifa) == NULL) |
504 | return; | | 508 | return; |
505 | | | 509 | |
506 | in = &ifatoia(ifa)->ia_addr.sin_addr; | | 510 | in = &ifatoia(ifa)->ia_addr.sin_addr; |
507 | | | 511 | |
508 | arprequest(ifa->ifa_ifp, in, in, | | 512 | arprequest(ifa->ifa_ifp, in, in, |
509 | CLLADDR(ifa->ifa_ifp->if_sadl)); | | 513 | CLLADDR(ifa->ifa_ifp->if_sadl)); |
510 | return; | | 514 | return; |
511 | } | | 515 | } |
512 | | | 516 | |
513 | if ((rt->rt_flags & RTF_GATEWAY) != 0) { | | 517 | if ((rt->rt_flags & RTF_GATEWAY) != 0) { |
514 | if (req != RTM_ADD) | | 518 | if (req != RTM_ADD) |
515 | return; | | 519 | return; |
516 | | | 520 | |
517 | /* | | 521 | /* |
518 | * linklayers with particular link MTU limitation. | | 522 | * linklayers with particular link MTU limitation. |
519 | */ | | 523 | */ |
520 | switch(ifp->if_type) { | | 524 | switch(ifp->if_type) { |
521 | #if NFDDI > 0 | | 525 | #if NFDDI > 0 |
522 | case IFT_FDDI: | | 526 | case IFT_FDDI: |
523 | if (ifp->if_mtu > FDDIIPMTU) | | 527 | if (ifp->if_mtu > FDDIIPMTU) |
524 | rt->rt_rmx.rmx_mtu = FDDIIPMTU; | | 528 | rt->rt_rmx.rmx_mtu = FDDIIPMTU; |
525 | break; | | 529 | break; |
526 | #endif | | 530 | #endif |
527 | #if NARC > 0 | | 531 | #if NARC > 0 |
528 | case IFT_ARCNET: | | 532 | case IFT_ARCNET: |
529 | { | | 533 | { |
530 | int arcipifmtu; | | 534 | int arcipifmtu; |
531 | | | 535 | |
532 | if (ifp->if_flags & IFF_LINK0) | | 536 | if (ifp->if_flags & IFF_LINK0) |
533 | arcipifmtu = arc_ipmtu; | | 537 | arcipifmtu = arc_ipmtu; |
534 | else | | 538 | else |
535 | arcipifmtu = ARCMTU; | | 539 | arcipifmtu = ARCMTU; |
536 | if (ifp->if_mtu > arcipifmtu) | | 540 | if (ifp->if_mtu > arcipifmtu) |
537 | rt->rt_rmx.rmx_mtu = arcipifmtu; | | 541 | rt->rt_rmx.rmx_mtu = arcipifmtu; |
538 | break; | | 542 | break; |
539 | } | | 543 | } |
540 | #endif | | 544 | #endif |
541 | } | | 545 | } |
542 | return; | | 546 | return; |
543 | } | | 547 | } |
544 | | | 548 | |
545 | ARP_LOCK(1); /* we may already be locked here. */ | | 549 | ARP_LOCK(1); /* we may already be locked here. */ |
546 | | | 550 | |
547 | switch (req) { | | 551 | switch (req) { |
548 | case RTM_SETGATE: | | 552 | case RTM_SETGATE: |
549 | gate = arp_setgate(rt, gate, info->rti_info[RTAX_NETMASK]); | | 553 | gate = arp_setgate(rt, gate, info->rti_info[RTAX_NETMASK]); |
550 | break; | | 554 | break; |
551 | case RTM_ADD: | | 555 | case RTM_ADD: |
552 | gate = arp_setgate(rt, gate, info->rti_info[RTAX_NETMASK]); | | 556 | gate = arp_setgate(rt, gate, info->rti_info[RTAX_NETMASK]); |
553 | if (rt->rt_flags & RTF_CLONING) { | | 557 | if (rt->rt_flags & RTF_CLONING) { |
554 | /* | | 558 | /* |
555 | * Give this route an expiration time, even though | | 559 | * Give this route an expiration time, even though |
556 | * it's a "permanent" route, so that routes cloned | | 560 | * it's a "permanent" route, so that routes cloned |
557 | * from it do not need their expiration time set. | | 561 | * from it do not need their expiration time set. |
558 | */ | | 562 | */ |
559 | rt->rt_expire = time_second; | | 563 | rt->rt_expire = time_second; |
560 | /* | | 564 | /* |
561 | * linklayers with particular link MTU limitation. | | 565 | * linklayers with particular link MTU limitation. |
562 | */ | | 566 | */ |
563 | switch (ifp->if_type) { | | 567 | switch (ifp->if_type) { |
564 | #if NFDDI > 0 | | 568 | #if NFDDI > 0 |
565 | case IFT_FDDI: | | 569 | case IFT_FDDI: |
566 | if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0 && | | 570 | if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0 && |
567 | (rt->rt_rmx.rmx_mtu > FDDIIPMTU || | | 571 | (rt->rt_rmx.rmx_mtu > FDDIIPMTU || |
568 | (rt->rt_rmx.rmx_mtu == 0 && | | 572 | (rt->rt_rmx.rmx_mtu == 0 && |
569 | ifp->if_mtu > FDDIIPMTU))) | | 573 | ifp->if_mtu > FDDIIPMTU))) |
570 | rt->rt_rmx.rmx_mtu = FDDIIPMTU; | | 574 | rt->rt_rmx.rmx_mtu = FDDIIPMTU; |
571 | break; | | 575 | break; |
572 | #endif | | 576 | #endif |
573 | #if NARC > 0 | | 577 | #if NARC > 0 |
574 | case IFT_ARCNET: | | 578 | case IFT_ARCNET: |
575 | { | | 579 | { |
576 | int arcipifmtu; | | 580 | int arcipifmtu; |
577 | if (ifp->if_flags & IFF_LINK0) | | 581 | if (ifp->if_flags & IFF_LINK0) |
578 | arcipifmtu = arc_ipmtu; | | 582 | arcipifmtu = arc_ipmtu; |
579 | else | | 583 | else |
580 | arcipifmtu = ARCMTU; | | 584 | arcipifmtu = ARCMTU; |
581 | | | 585 | |
582 | if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0 && | | 586 | if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0 && |
583 | (rt->rt_rmx.rmx_mtu > arcipifmtu || | | 587 | (rt->rt_rmx.rmx_mtu > arcipifmtu || |
584 | (rt->rt_rmx.rmx_mtu == 0 && | | 588 | (rt->rt_rmx.rmx_mtu == 0 && |
585 | ifp->if_mtu > arcipifmtu))) | | 589 | ifp->if_mtu > arcipifmtu))) |
586 | rt->rt_rmx.rmx_mtu = arcipifmtu; | | 590 | rt->rt_rmx.rmx_mtu = arcipifmtu; |
587 | break; | | 591 | break; |
588 | } | | 592 | } |
589 | #endif | | 593 | #endif |
590 | } | | 594 | } |
591 | break; | | 595 | break; |
592 | } | | 596 | } |
593 | /* Announce a new entry if requested. */ | | 597 | /* Announce a new entry if requested. */ |
594 | if (rt->rt_flags & RTF_ANNOUNCE) { | | 598 | if (rt->rt_flags & RTF_ANNOUNCE) { |
595 | arprequest(ifp, | | 599 | arprequest(ifp, |
596 | &satocsin(rt_getkey(rt))->sin_addr, | | 600 | &satocsin(rt_getkey(rt))->sin_addr, |
597 | &satocsin(rt_getkey(rt))->sin_addr, | | 601 | &satocsin(rt_getkey(rt))->sin_addr, |
598 | CLLADDR(satocsdl(gate))); | | 602 | CLLADDR(satocsdl(gate))); |
599 | } | | 603 | } |
600 | /*FALLTHROUGH*/ | | 604 | /*FALLTHROUGH*/ |
601 | case RTM_RESOLVE: | | 605 | case RTM_RESOLVE: |
602 | if (gate->sa_family != AF_LINK || | | 606 | if (gate->sa_family != AF_LINK || |
603 | gate->sa_len < sockaddr_dl_measure(0, ifp->if_addrlen)) { | | 607 | gate->sa_len < sockaddr_dl_measure(0, ifp->if_addrlen)) { |
604 | log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n"); | | 608 | log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n"); |
605 | break; | | 609 | break; |
606 | } | | 610 | } |
607 | satosdl(gate)->sdl_type = ifp->if_type; | | 611 | satosdl(gate)->sdl_type = ifp->if_type; |
608 | satosdl(gate)->sdl_index = ifp->if_index; | | 612 | satosdl(gate)->sdl_index = ifp->if_index; |
609 | if (la != NULL) | | 613 | if (la != NULL) |
610 | break; /* This happens on a route change */ | | 614 | break; /* This happens on a route change */ |
611 | /* | | 615 | /* |
612 | * Case 2: This route may come from cloning, or a manual route | | 616 | * Case 2: This route may come from cloning, or a manual route |
613 | * add with a LL address. | | 617 | * add with a LL address. |
614 | */ | | 618 | */ |
615 | switch (ifp->if_type) { | | 619 | switch (ifp->if_type) { |
616 | #if NTOKEN > 0 | | 620 | #if NTOKEN > 0 |
617 | case IFT_ISO88025: | | 621 | case IFT_ISO88025: |
618 | allocsize = sizeof(*la) + sizeof(struct token_rif); | | 622 | allocsize = sizeof(*la) + sizeof(struct token_rif); |
619 | break; | | 623 | break; |
620 | #endif /* NTOKEN > 0 */ | | 624 | #endif /* NTOKEN > 0 */ |
621 | default: | | 625 | default: |
622 | allocsize = sizeof(*la); | | 626 | allocsize = sizeof(*la); |
623 | } | | 627 | } |
624 | R_Malloc(la, struct llinfo_arp *, allocsize); | | 628 | R_Malloc(la, struct llinfo_arp *, allocsize); |
625 | rt->rt_llinfo = (void *)la; | | 629 | rt->rt_llinfo = (void *)la; |
626 | if (la == NULL) { | | 630 | if (la == NULL) { |
627 | log(LOG_DEBUG, "arp_rtrequest: malloc failed\n"); | | 631 | log(LOG_DEBUG, "arp_rtrequest: malloc failed\n"); |
628 | break; | | 632 | break; |
629 | } | | 633 | } |
630 | arp_inuse++, arp_allocated++; | | 634 | arp_inuse++, arp_allocated++; |
631 | memset(la, 0, allocsize); | | 635 | memset(la, 0, allocsize); |
632 | la->la_rt = rt; | | 636 | la->la_rt = rt; |
633 | rt->rt_flags |= RTF_LLINFO; | | 637 | rt->rt_flags |= RTF_LLINFO; |
634 | LIST_INSERT_HEAD(&llinfo_arp, la, la_list); | | 638 | LIST_INSERT_HEAD(&llinfo_arp, la, la_list); |
635 | | | 639 | |
636 | INADDR_TO_IA(satocsin(rt_getkey(rt))->sin_addr, ia); | | 640 | INADDR_TO_IA(satocsin(rt_getkey(rt))->sin_addr, ia); |
637 | while (ia && ia->ia_ifp != ifp) | | 641 | while (ia && ia->ia_ifp != ifp) |
638 | NEXT_IA_WITH_SAME_ADDR(ia); | | 642 | NEXT_IA_WITH_SAME_ADDR(ia); |
639 | if (ia) { | | 643 | if (ia) { |
640 | /* | | 644 | /* |
641 | * This test used to be | | 645 | * This test used to be |
642 | * if (lo0ifp->if_flags & IFF_UP) | | 646 | * if (lo0ifp->if_flags & IFF_UP) |
643 | * It allowed local traffic to be forced through | | 647 | * It allowed local traffic to be forced through |
644 | * the hardware by configuring the loopback down. | | 648 | * the hardware by configuring the loopback down. |
645 | * However, it causes problems during network | | 649 | * However, it causes problems during network |
646 | * configuration for boards that can't receive | | 650 | * configuration for boards that can't receive |
647 | * packets they send. It is now necessary to clear | | 651 | * packets they send. It is now necessary to clear |
648 | * "useloopback" and remove the route to force | | 652 | * "useloopback" and remove the route to force |
649 | * traffic out to the hardware. | | 653 | * traffic out to the hardware. |
650 | * | | 654 | * |
651 | * In 4.4BSD, the above "if" statement checked | | 655 | * In 4.4BSD, the above "if" statement checked |
652 | * rt->rt_ifa against rt_getkey(rt). It was changed | | 656 | * rt->rt_ifa against rt_getkey(rt). It was changed |
653 | * to the current form so that we can provide a | | 657 | * to the current form so that we can provide a |
654 | * better support for multiple IPv4 addresses on a | | 658 | * better support for multiple IPv4 addresses on a |
655 | * interface. | | 659 | * interface. |
656 | */ | | 660 | */ |
657 | rt->rt_expire = 0; | | 661 | rt->rt_expire = 0; |
658 | if (sockaddr_dl_init(satosdl(gate), gate->sa_len, | | 662 | if (sockaddr_dl_init(satosdl(gate), gate->sa_len, |
659 | ifp->if_index, ifp->if_type, NULL, 0, | | 663 | ifp->if_index, ifp->if_type, NULL, 0, |
660 | CLLADDR(ifp->if_sadl), ifp->if_addrlen) == NULL) { | | 664 | CLLADDR(ifp->if_sadl), ifp->if_addrlen) == NULL) { |
661 | panic("%s(%s): sockaddr_dl_init cannot fail", | | 665 | panic("%s(%s): sockaddr_dl_init cannot fail", |
662 | __func__, ifp->if_xname); | | 666 | __func__, ifp->if_xname); |
663 | } | | 667 | } |
664 | if (useloopback) | | 668 | if (useloopback) |
665 | ifp = rt->rt_ifp = lo0ifp; | | 669 | ifp = rt->rt_ifp = lo0ifp; |
666 | /* | | 670 | /* |
667 | * make sure to set rt->rt_ifa to the interface | | 671 | * make sure to set rt->rt_ifa to the interface |
668 | * address we are using, otherwise we will have trouble | | 672 | * address we are using, otherwise we will have trouble |
669 | * with source address selection. | | 673 | * with source address selection. |
670 | */ | | 674 | */ |
671 | ifa = &ia->ia_ifa; | | 675 | ifa = &ia->ia_ifa; |
672 | if (ifa != rt->rt_ifa) | | 676 | if (ifa != rt->rt_ifa) |
673 | rt_replace_ifa(rt, ifa); | | 677 | rt_replace_ifa(rt, ifa); |
674 | } | | 678 | } |
675 | break; | | 679 | break; |
676 | | | 680 | |
677 | case RTM_DELETE: | | 681 | case RTM_DELETE: |
678 | if (la == NULL) | | 682 | if (la == NULL) |
679 | break; | | 683 | break; |
680 | arp_inuse--; | | 684 | arp_inuse--; |
681 | LIST_REMOVE(la, la_list); | | 685 | LIST_REMOVE(la, la_list); |
682 | rt->rt_llinfo = NULL; | | 686 | rt->rt_llinfo = NULL; |
683 | rt->rt_flags &= ~RTF_LLINFO; | | 687 | rt->rt_flags &= ~RTF_LLINFO; |
684 | | | 688 | |
685 | s = splnet(); | | 689 | s = splnet(); |
686 | mold = la->la_hold; | | 690 | mold = la->la_hold; |
687 | la->la_hold = 0; | | 691 | la->la_hold = 0; |
688 | splx(s); | | 692 | splx(s); |
689 | | | 693 | |
690 | if (mold) | | 694 | if (mold) |
691 | m_freem(mold); | | 695 | m_freem(mold); |
692 | | | 696 | |
693 | Free((void *)la); | | 697 | Free((void *)la); |
694 | } | | 698 | } |
695 | ARP_UNLOCK(); | | 699 | ARP_UNLOCK(); |
696 | } | | 700 | } |
697 | | | 701 | |
698 | /* | | 702 | /* |
699 | * Broadcast an ARP request. Caller specifies: | | 703 | * Broadcast an ARP request. Caller specifies: |
700 | * - arp header source ip address | | 704 | * - arp header source ip address |
701 | * - arp header target ip address | | 705 | * - arp header target ip address |
702 | * - arp header source ethernet address | | 706 | * - arp header source ethernet address |
703 | */ | | 707 | */ |
704 | void | | 708 | void |
705 | arprequest(struct ifnet *ifp, | | 709 | arprequest(struct ifnet *ifp, |
706 | const struct in_addr *sip, const struct in_addr *tip, | | 710 | const struct in_addr *sip, const struct in_addr *tip, |
707 | const u_int8_t *enaddr) | | 711 | const u_int8_t *enaddr) |
708 | { | | 712 | { |
709 | struct mbuf *m; | | 713 | struct mbuf *m; |
710 | struct arphdr *ah; | | 714 | struct arphdr *ah; |
711 | struct sockaddr sa; | | 715 | struct sockaddr sa; |
712 | uint64_t *arps; | | 716 | uint64_t *arps; |
713 | | | 717 | |
714 | if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) | | 718 | if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) |
715 | return; | | 719 | return; |
716 | MCLAIM(m, &arpdomain.dom_mowner); | | 720 | MCLAIM(m, &arpdomain.dom_mowner); |
717 | switch (ifp->if_type) { | | 721 | switch (ifp->if_type) { |
718 | case IFT_IEEE1394: | | 722 | case IFT_IEEE1394: |
719 | m->m_len = sizeof(*ah) + 2 * sizeof(struct in_addr) + | | 723 | m->m_len = sizeof(*ah) + 2 * sizeof(struct in_addr) + |
720 | ifp->if_addrlen; | | 724 | ifp->if_addrlen; |
721 | break; | | 725 | break; |
722 | default: | | 726 | default: |
723 | m->m_len = sizeof(*ah) + 2 * sizeof(struct in_addr) + | | 727 | m->m_len = sizeof(*ah) + 2 * sizeof(struct in_addr) + |
724 | 2 * ifp->if_addrlen; | | 728 | 2 * ifp->if_addrlen; |
725 | break; | | 729 | break; |
726 | } | | 730 | } |
727 | m->m_pkthdr.len = m->m_len; | | 731 | m->m_pkthdr.len = m->m_len; |
728 | MH_ALIGN(m, m->m_len); | | 732 | MH_ALIGN(m, m->m_len); |
729 | ah = mtod(m, struct arphdr *); | | 733 | ah = mtod(m, struct arphdr *); |
730 | memset(ah, 0, m->m_len); | | 734 | memset(ah, 0, m->m_len); |
731 | switch (ifp->if_type) { | | 735 | switch (ifp->if_type) { |
732 | case IFT_IEEE1394: /* RFC2734 */ | | 736 | case IFT_IEEE1394: /* RFC2734 */ |
733 | /* fill it now for ar_tpa computation */ | | 737 | /* fill it now for ar_tpa computation */ |
734 | ah->ar_hrd = htons(ARPHRD_IEEE1394); | | 738 | ah->ar_hrd = htons(ARPHRD_IEEE1394); |
735 | break; | | 739 | break; |
736 | default: | | 740 | default: |
737 | /* ifp->if_output will fill ar_hrd */ | | 741 | /* ifp->if_output will fill ar_hrd */ |
738 | break; | | 742 | break; |
739 | } | | 743 | } |
740 | ah->ar_pro = htons(ETHERTYPE_IP); | | 744 | ah->ar_pro = htons(ETHERTYPE_IP); |
741 | ah->ar_hln = ifp->if_addrlen; /* hardware address length */ | | 745 | ah->ar_hln = ifp->if_addrlen; /* hardware address length */ |
742 | ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ | | 746 | ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ |
743 | ah->ar_op = htons(ARPOP_REQUEST); | | 747 | ah->ar_op = htons(ARPOP_REQUEST); |
744 | memcpy(ar_sha(ah), enaddr, ah->ar_hln); | | 748 | memcpy(ar_sha(ah), enaddr, ah->ar_hln); |
745 | memcpy(ar_spa(ah), sip, ah->ar_pln); | | 749 | memcpy(ar_spa(ah), sip, ah->ar_pln); |
746 | memcpy(ar_tpa(ah), tip, ah->ar_pln); | | 750 | memcpy(ar_tpa(ah), tip, ah->ar_pln); |
747 | sa.sa_family = AF_ARP; | | 751 | sa.sa_family = AF_ARP; |
748 | sa.sa_len = 2; | | 752 | sa.sa_len = 2; |
749 | m->m_flags |= M_BCAST; | | 753 | m->m_flags |= M_BCAST; |
750 | arps = ARP_STAT_GETREF(); | | 754 | arps = ARP_STAT_GETREF(); |
751 | arps[ARP_STAT_SNDTOTAL]++; | | 755 | arps[ARP_STAT_SNDTOTAL]++; |
752 | arps[ARP_STAT_SENDREQUEST]++; | | 756 | arps[ARP_STAT_SENDREQUEST]++; |
753 | ARP_STAT_PUTREF(); | | 757 | ARP_STAT_PUTREF(); |
754 | (*ifp->if_output)(ifp, m, &sa, NULL); | | 758 | (*ifp->if_output)(ifp, m, &sa, NULL); |
755 | } | | 759 | } |
756 | | | 760 | |
757 | /* | | 761 | /* |
758 | * Resolve an IP address into an ethernet address. If success, | | 762 | * Resolve an IP address into an ethernet address. If success, |
759 | * desten is filled in. If there is no entry in arptab, | | 763 | * desten is filled in. If there is no entry in arptab, |
760 | * set one up and broadcast a request for the IP address. | | 764 | * set one up and broadcast a request for the IP address. |
761 | * Hold onto this mbuf and resend it once the address | | 765 | * Hold onto this mbuf and resend it once the address |
762 | * is finally resolved. A return value of 1 indicates | | 766 | * is finally resolved. A return value of 1 indicates |
763 | * that desten has been filled in and the packet should be sent | | 767 | * that desten has been filled in and the packet should be sent |
764 | * normally; a 0 return indicates that the packet has been | | 768 | * normally; a 0 return indicates that the packet has been |
765 | * taken over here, either now or for later transmission. | | 769 | * taken over here, either now or for later transmission. |
766 | */ | | 770 | */ |
767 | int | | 771 | int |
768 | arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m, | | 772 | arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m, |
769 | const struct sockaddr *dst, u_char *desten) | | 773 | const struct sockaddr *dst, u_char *desten) |
770 | { | | 774 | { |
771 | struct llinfo_arp *la; | | 775 | struct llinfo_arp *la; |
772 | const struct sockaddr_dl *sdl; | | 776 | const struct sockaddr_dl *sdl; |
773 | struct mbuf *mold; | | 777 | struct mbuf *mold; |
774 | int s; | | 778 | int s; |
775 | | | 779 | |
776 | if ((la = arplookup1(m, &satocsin(dst)->sin_addr, 1, 0, rt)) != NULL) | | 780 | if ((la = arplookup1(m, &satocsin(dst)->sin_addr, 1, 0, rt)) != NULL) |
777 | rt = la->la_rt; | | 781 | rt = la->la_rt; |
778 | | | 782 | |
779 | if (la == NULL || rt == NULL) { | | 783 | if (la == NULL || rt == NULL) { |
780 | ARP_STATINC(ARP_STAT_ALLOCFAIL); | | 784 | ARP_STATINC(ARP_STAT_ALLOCFAIL); |
781 | log(LOG_DEBUG, | | 785 | log(LOG_DEBUG, |
782 | "arpresolve: can't allocate llinfo on %s for %s\n", | | 786 | "arpresolve: can't allocate llinfo on %s for %s\n", |
783 | ifp->if_xname, in_fmtaddr(satocsin(dst)->sin_addr)); | | 787 | ifp->if_xname, in_fmtaddr(satocsin(dst)->sin_addr)); |
784 | m_freem(m); | | 788 | m_freem(m); |
785 | return 0; | | 789 | return 0; |
786 | } | | 790 | } |
787 | sdl = satocsdl(rt->rt_gateway); | | 791 | sdl = satocsdl(rt->rt_gateway); |
788 | /* | | 792 | /* |
789 | * Check the address family and length is valid, the address | | 793 | * Check the address family and length is valid, the address |
790 | * is resolved; otherwise, try to resolve. | | 794 | * is resolved; otherwise, try to resolve. |
791 | */ | | 795 | */ |
792 | if ((rt->rt_expire == 0 || rt->rt_expire > time_second) && | | 796 | if ((rt->rt_expire == 0 || rt->rt_expire > time_second) && |
793 | sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { | | 797 | sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { |
794 | memcpy(desten, CLLADDR(sdl), | | 798 | memcpy(desten, CLLADDR(sdl), |
795 | min(sdl->sdl_alen, ifp->if_addrlen)); | | 799 | min(sdl->sdl_alen, ifp->if_addrlen)); |
796 | rt->rt_pksent = time_second; /* Time for last pkt sent */ | | 800 | rt->rt_pksent = time_second; /* Time for last pkt sent */ |
797 | return 1; | | 801 | return 1; |
798 | } | | 802 | } |
799 | /* | | 803 | /* |
800 | * There is an arptab entry, but no ethernet address | | 804 | * There is an arptab entry, but no ethernet address |
801 | * response yet. Replace the held mbuf with this | | 805 | * response yet. Replace the held mbuf with this |
802 | * latest one. | | 806 | * latest one. |
803 | */ | | 807 | */ |
804 | | | 808 | |
805 | ARP_STATINC(ARP_STAT_DFRTOTAL); | | 809 | ARP_STATINC(ARP_STAT_DFRTOTAL); |
806 | s = splnet(); | | 810 | s = splnet(); |
807 | mold = la->la_hold; | | 811 | mold = la->la_hold; |
808 | la->la_hold = m; | | 812 | la->la_hold = m; |
809 | splx(s); | | 813 | splx(s); |
810 | | | 814 | |
811 | if (mold) { | | 815 | if (mold) { |
812 | ARP_STATINC(ARP_STAT_DFRDROPPED); | | 816 | ARP_STATINC(ARP_STAT_DFRDROPPED); |
813 | m_freem(mold); | | 817 | m_freem(mold); |
814 | } | | 818 | } |
815 | | | 819 | |
816 | /* | | 820 | /* |
817 | * Re-send the ARP request when appropriate. | | 821 | * Re-send the ARP request when appropriate. |
818 | */ | | 822 | */ |
819 | #ifdef DIAGNOSTIC | | 823 | #ifdef DIAGNOSTIC |
820 | if (rt->rt_expire == 0) { | | 824 | if (rt->rt_expire == 0) { |
821 | /* This should never happen. (Should it? -gwr) */ | | 825 | /* This should never happen. (Should it? -gwr) */ |
822 | printf("arpresolve: unresolved and rt_expire == 0\n"); | | 826 | printf("arpresolve: unresolved and rt_expire == 0\n"); |
823 | /* Set expiration time to now (expired). */ | | 827 | /* Set expiration time to now (expired). */ |
824 | rt->rt_expire = time_second; | | 828 | rt->rt_expire = time_second; |
825 | } | | 829 | } |
826 | #endif | | 830 | #endif |
827 | if (rt->rt_expire) { | | 831 | if (rt->rt_expire) { |
828 | rt->rt_flags &= ~RTF_REJECT; | | 832 | rt->rt_flags &= ~RTF_REJECT; |
829 | if (la->la_asked == 0 || rt->rt_expire != time_second) { | | 833 | if (la->la_asked == 0 || rt->rt_expire != time_second) { |
830 | rt->rt_expire = time_second; | | 834 | rt->rt_expire = time_second; |
831 | if (la->la_asked++ < arp_maxtries) { | | 835 | if (la->la_asked++ < arp_maxtries) { |
832 | arprequest(ifp, | | 836 | arprequest(ifp, |
833 | &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, | | 837 | &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, |
834 | &satocsin(dst)->sin_addr, | | 838 | &satocsin(dst)->sin_addr, |
835 | #if NCARP > 0 | | 839 | #if NCARP > 0 |
836 | (rt->rt_ifp->if_type == IFT_CARP) ? | | 840 | (rt->rt_ifp->if_type == IFT_CARP) ? |
837 | CLLADDR(rt->rt_ifp->if_sadl): | | 841 | CLLADDR(rt->rt_ifp->if_sadl): |
838 | #endif | | 842 | #endif |
839 | CLLADDR(ifp->if_sadl)); | | 843 | CLLADDR(ifp->if_sadl)); |
840 | } else { | | 844 | } else { |
841 | rt->rt_flags |= RTF_REJECT; | | 845 | rt->rt_flags |= RTF_REJECT; |
842 | rt->rt_expire += arpt_down; | | 846 | rt->rt_expire += arpt_down; |
843 | la->la_asked = 0; | | 847 | la->la_asked = 0; |
844 | } | | 848 | } |
845 | } | | 849 | } |
846 | } | | 850 | } |
847 | return 0; | | 851 | return 0; |
848 | } | | 852 | } |
849 | | | 853 | |
850 | /* | | 854 | /* |
851 | * Common length and type checks are done here, | | 855 | * Common length and type checks are done here, |
852 | * then the protocol-specific routine is called. | | 856 | * then the protocol-specific routine is called. |
853 | */ | | 857 | */ |
854 | void | | 858 | void |
855 | arpintr(void) | | 859 | arpintr(void) |
856 | { | | 860 | { |
857 | struct mbuf *m; | | 861 | struct mbuf *m; |
858 | struct arphdr *ar; | | 862 | struct arphdr *ar; |
859 | int s; | | 863 | int s; |
860 | int arplen; | | 864 | int arplen; |
861 | | | 865 | |
862 | mutex_enter(softnet_lock); | | 866 | mutex_enter(softnet_lock); |
863 | KERNEL_LOCK(1, NULL); | | 867 | KERNEL_LOCK(1, NULL); |
864 | while (arpintrq.ifq_head) { | | 868 | while (arpintrq.ifq_head) { |
865 | s = splnet(); | | 869 | s = splnet(); |
866 | IF_DEQUEUE(&arpintrq, m); | | 870 | IF_DEQUEUE(&arpintrq, m); |
867 | splx(s); | | 871 | splx(s); |
868 | if (m == 0 || (m->m_flags & M_PKTHDR) == 0) | | 872 | if (m == 0 || (m->m_flags & M_PKTHDR) == 0) |
869 | panic("arpintr"); | | 873 | panic("arpintr"); |
870 | | | 874 | |
871 | MCLAIM(m, &arpdomain.dom_mowner); | | 875 | MCLAIM(m, &arpdomain.dom_mowner); |
872 | ARP_STATINC(ARP_STAT_RCVTOTAL); | | 876 | ARP_STATINC(ARP_STAT_RCVTOTAL); |
873 | | | 877 | |
874 | /* | | 878 | /* |
875 | * First, make sure we have at least struct arphdr. | | 879 | * First, make sure we have at least struct arphdr. |
876 | */ | | 880 | */ |
877 | if (m->m_len < sizeof(struct arphdr) || | | 881 | if (m->m_len < sizeof(struct arphdr) || |
878 | (ar = mtod(m, struct arphdr *)) == NULL) | | 882 | (ar = mtod(m, struct arphdr *)) == NULL) |
879 | goto badlen; | | 883 | goto badlen; |
880 | | | 884 | |
881 | switch (m->m_pkthdr.rcvif->if_type) { | | 885 | switch (m->m_pkthdr.rcvif->if_type) { |
882 | case IFT_IEEE1394: | | 886 | case IFT_IEEE1394: |
883 | arplen = sizeof(struct arphdr) + | | 887 | arplen = sizeof(struct arphdr) + |
884 | ar->ar_hln + 2 * ar->ar_pln; | | 888 | ar->ar_hln + 2 * ar->ar_pln; |
885 | break; | | 889 | break; |
886 | default: | | 890 | default: |
887 | arplen = sizeof(struct arphdr) + | | 891 | arplen = sizeof(struct arphdr) + |
888 | 2 * ar->ar_hln + 2 * ar->ar_pln; | | 892 | 2 * ar->ar_hln + 2 * ar->ar_pln; |
889 | break; | | 893 | break; |
890 | } | | 894 | } |
891 | | | 895 | |
892 | if (/* XXX ntohs(ar->ar_hrd) == ARPHRD_ETHER && */ | | 896 | if (/* XXX ntohs(ar->ar_hrd) == ARPHRD_ETHER && */ |
893 | m->m_len >= arplen) | | 897 | m->m_len >= arplen) |
894 | switch (ntohs(ar->ar_pro)) { | | 898 | switch (ntohs(ar->ar_pro)) { |
895 | case ETHERTYPE_IP: | | 899 | case ETHERTYPE_IP: |
896 | case ETHERTYPE_IPTRAILERS: | | 900 | case ETHERTYPE_IPTRAILERS: |
897 | in_arpinput(m); | | 901 | in_arpinput(m); |
898 | continue; | | 902 | continue; |
899 | default: | | 903 | default: |
900 | ARP_STATINC(ARP_STAT_RCVBADPROTO); | | 904 | ARP_STATINC(ARP_STAT_RCVBADPROTO); |
901 | } | | 905 | } |
902 | else { | | 906 | else { |
903 | badlen: | | 907 | badlen: |
904 | ARP_STATINC(ARP_STAT_RCVBADLEN); | | 908 | ARP_STATINC(ARP_STAT_RCVBADLEN); |
905 | } | | 909 | } |
906 | m_freem(m); | | 910 | m_freem(m); |
907 | } | | 911 | } |
908 | KERNEL_UNLOCK_ONE(NULL); | | 912 | KERNEL_UNLOCK_ONE(NULL); |
909 | mutex_exit(softnet_lock); | | 913 | mutex_exit(softnet_lock); |
910 | } | | 914 | } |
911 | | | 915 | |
912 | /* | | 916 | /* |
913 | * ARP for Internet protocols on 10 Mb/s Ethernet. | | 917 | * ARP for Internet protocols on 10 Mb/s Ethernet. |
914 | * Algorithm is that given in RFC 826. | | 918 | * Algorithm is that given in RFC 826. |
915 | * In addition, a sanity check is performed on the sender | | 919 | * In addition, a sanity check is performed on the sender |
916 | * protocol address, to catch impersonators. | | 920 | * protocol address, to catch impersonators. |
917 | * We no longer handle negotiations for use of trailer protocol: | | 921 | * We no longer handle negotiations for use of trailer protocol: |
918 | * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent | | 922 | * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent |
919 | * along with IP replies if we wanted trailers sent to us, | | 923 | * along with IP replies if we wanted trailers sent to us, |
920 | * and also sent them in response to IP replies. | | 924 | * and also sent them in response to IP replies. |
921 | * This allowed either end to announce the desire to receive | | 925 | * This allowed either end to announce the desire to receive |
922 | * trailer packets. | | 926 | * trailer packets. |
923 | * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, | | 927 | * We no longer reply to requests for ETHERTYPE_TRAIL protocol either, |
924 | * but formerly didn't normally send requests. | | 928 | * but formerly didn't normally send requests. |
925 | */ | | 929 | */ |
926 | static void | | 930 | static void |
927 | in_arpinput(struct mbuf *m) | | 931 | in_arpinput(struct mbuf *m) |
928 | { | | 932 | { |
929 | struct arphdr *ah; | | 933 | struct arphdr *ah; |
930 | struct ifnet *ifp = m->m_pkthdr.rcvif; | | 934 | struct ifnet *ifp = m->m_pkthdr.rcvif; |
931 | struct llinfo_arp *la = NULL; | | 935 | struct llinfo_arp *la = NULL; |
932 | struct rtentry *rt; | | 936 | struct rtentry *rt; |
933 | struct in_ifaddr *ia; | | 937 | struct in_ifaddr *ia; |
934 | #if NBRIDGE > 0 | | 938 | #if NBRIDGE > 0 |
935 | struct in_ifaddr *bridge_ia = NULL; | | 939 | struct in_ifaddr *bridge_ia = NULL; |
936 | #endif | | 940 | #endif |
937 | #if NCARP > 0 | | 941 | #if NCARP > 0 |
938 | u_int32_t count = 0, index = 0; | | 942 | u_int32_t count = 0, index = 0; |
939 | #endif | | 943 | #endif |
940 | struct sockaddr_dl *sdl; | | 944 | struct sockaddr_dl *sdl; |
941 | struct sockaddr sa; | | 945 | struct sockaddr sa; |
942 | struct in_addr isaddr, itaddr, myaddr; | | 946 | struct in_addr isaddr, itaddr, myaddr; |
943 | int op; | | 947 | int op; |
944 | struct mbuf *mold; | | 948 | struct mbuf *mold; |
945 | void *tha; | | 949 | void *tha; |
946 | int s; | | 950 | int s; |
947 | uint64_t *arps; | | 951 | uint64_t *arps; |
948 | | | 952 | |
949 | if (__predict_false(m_makewritable(&m, 0, m->m_pkthdr.len, M_DONTWAIT))) | | 953 | if (__predict_false(m_makewritable(&m, 0, m->m_pkthdr.len, M_DONTWAIT))) |
950 | goto out; | | 954 | goto out; |
951 | ah = mtod(m, struct arphdr *); | | 955 | ah = mtod(m, struct arphdr *); |
952 | op = ntohs(ah->ar_op); | | 956 | op = ntohs(ah->ar_op); |
953 | | | 957 | |
954 | /* | | 958 | /* |
955 | * Fix up ah->ar_hrd if necessary, before using ar_tha() or | | 959 | * Fix up ah->ar_hrd if necessary, before using ar_tha() or |
956 | * ar_tpa(). | | 960 | * ar_tpa(). |
957 | */ | | 961 | */ |
958 | switch (ifp->if_type) { | | 962 | switch (ifp->if_type) { |
959 | case IFT_IEEE1394: | | 963 | case IFT_IEEE1394: |
960 | if (ntohs(ah->ar_hrd) == ARPHRD_IEEE1394) | | 964 | if (ntohs(ah->ar_hrd) == ARPHRD_IEEE1394) |
961 | ; | | 965 | ; |
962 | else { | | 966 | else { |
963 | /* XXX this is to make sure we compute ar_tha right */ | | 967 | /* XXX this is to make sure we compute ar_tha right */ |
964 | /* XXX check ar_hrd more strictly? */ | | 968 | /* XXX check ar_hrd more strictly? */ |
965 | ah->ar_hrd = htons(ARPHRD_IEEE1394); | | 969 | ah->ar_hrd = htons(ARPHRD_IEEE1394); |
966 | } | | 970 | } |
967 | break; | | 971 | break; |
968 | default: | | 972 | default: |
969 | /* XXX check ar_hrd? */ | | 973 | /* XXX check ar_hrd? */ |
970 | break; | | 974 | break; |
971 | } | | 975 | } |
972 | | | 976 | |
973 | memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); | | 977 | memcpy(&isaddr, ar_spa(ah), sizeof (isaddr)); |
974 | memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); | | 978 | memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); |
975 | | | 979 | |
976 | if (m->m_flags & (M_BCAST|M_MCAST)) | | 980 | if (m->m_flags & (M_BCAST|M_MCAST)) |
977 | ARP_STATINC(ARP_STAT_RCVMCAST); | | 981 | ARP_STATINC(ARP_STAT_RCVMCAST); |
978 | | | 982 | |
979 | /* | | 983 | /* |
980 | * If the target IP address is zero, ignore the packet. | | 984 | * If the target IP address is zero, ignore the packet. |
981 | * This prevents the code below from tring to answer | | 985 | * This prevents the code below from tring to answer |
982 | * when we are using IP address zero (booting). | | 986 | * when we are using IP address zero (booting). |
983 | */ | | 987 | */ |
984 | if (in_nullhost(itaddr)) { | | 988 | if (in_nullhost(itaddr)) { |
985 | ARP_STATINC(ARP_STAT_RCVZEROTPA); | | 989 | ARP_STATINC(ARP_STAT_RCVZEROTPA); |
986 | goto out; | | 990 | goto out; |
987 | } | | 991 | } |
988 | | | 992 | |
989 | | | 993 | |
990 | /* | | 994 | /* |
991 | * Search for a matching interface address | | 995 | * Search for a matching interface address |
992 | * or any address on the interface to use | | 996 | * or any address on the interface to use |
993 | * as a dummy address in the rest of this function | | 997 | * as a dummy address in the rest of this function |
994 | */ | | 998 | */ |
995 | | | 999 | |
996 | INADDR_TO_IA(itaddr, ia); | | 1000 | INADDR_TO_IA(itaddr, ia); |
997 | while (ia != NULL) { | | 1001 | while (ia != NULL) { |
998 | #if NCARP > 0 | | 1002 | #if NCARP > 0 |
999 | if (ia->ia_ifp->if_type == IFT_CARP && | | 1003 | if (ia->ia_ifp->if_type == IFT_CARP && |
1000 | ((ia->ia_ifp->if_flags & (IFF_UP|IFF_RUNNING)) == | | 1004 | ((ia->ia_ifp->if_flags & (IFF_UP|IFF_RUNNING)) == |
1001 | (IFF_UP|IFF_RUNNING))) { | | 1005 | (IFF_UP|IFF_RUNNING))) { |
1002 | index++; | | 1006 | index++; |
1003 | if (ia->ia_ifp == m->m_pkthdr.rcvif && | | 1007 | if (ia->ia_ifp == m->m_pkthdr.rcvif && |
1004 | carp_iamatch(ia, ar_sha(ah), | | 1008 | carp_iamatch(ia, ar_sha(ah), |
1005 | &count, index)) { | | 1009 | &count, index)) { |
1006 | break; | | 1010 | break; |
1007 | } | | 1011 | } |
1008 | } else | | 1012 | } else |
1009 | #endif | | 1013 | #endif |
1010 | if (ia->ia_ifp == m->m_pkthdr.rcvif) | | 1014 | if (ia->ia_ifp == m->m_pkthdr.rcvif) |
1011 | break; | | 1015 | break; |
1012 | #if NBRIDGE > 0 | | 1016 | #if NBRIDGE > 0 |
1013 | /* | | 1017 | /* |
1014 | * If the interface we received the packet on | | 1018 | * If the interface we received the packet on |
1015 | * is part of a bridge, check to see if we need | | 1019 | * is part of a bridge, check to see if we need |
1016 | * to "bridge" the packet to ourselves at this | | 1020 | * to "bridge" the packet to ourselves at this |
1017 | * layer. Note we still prefer a perfect match, | | 1021 | * layer. Note we still prefer a perfect match, |
1018 | * but allow this weaker match if necessary. | | 1022 | * but allow this weaker match if necessary. |
1019 | */ | | 1023 | */ |
1020 | if (m->m_pkthdr.rcvif->if_bridge != NULL && | | 1024 | if (m->m_pkthdr.rcvif->if_bridge != NULL && |
1021 | m->m_pkthdr.rcvif->if_bridge == ia->ia_ifp->if_bridge) | | 1025 | m->m_pkthdr.rcvif->if_bridge == ia->ia_ifp->if_bridge) |
1022 | bridge_ia = ia; | | 1026 | bridge_ia = ia; |
1023 | #endif /* NBRIDGE > 0 */ | | 1027 | #endif /* NBRIDGE > 0 */ |
1024 | | | 1028 | |
1025 | NEXT_IA_WITH_SAME_ADDR(ia); | | 1029 | NEXT_IA_WITH_SAME_ADDR(ia); |
1026 | } | | 1030 | } |
1027 | | | 1031 | |
1028 | #if NBRIDGE > 0 | | 1032 | #if NBRIDGE > 0 |
1029 | if (ia == NULL && bridge_ia != NULL) { | | 1033 | if (ia == NULL && bridge_ia != NULL) { |
1030 | ia = bridge_ia; | | 1034 | ia = bridge_ia; |
1031 | ifp = bridge_ia->ia_ifp; | | 1035 | ifp = bridge_ia->ia_ifp; |
1032 | } | | 1036 | } |
1033 | #endif | | 1037 | #endif |
1034 | | | 1038 | |
1035 | if (ia == NULL) { | | 1039 | if (ia == NULL) { |
1036 | INADDR_TO_IA(isaddr, ia); | | 1040 | INADDR_TO_IA(isaddr, ia); |
1037 | while ((ia != NULL) && ia->ia_ifp != m->m_pkthdr.rcvif) | | 1041 | while ((ia != NULL) && ia->ia_ifp != m->m_pkthdr.rcvif) |
1038 | NEXT_IA_WITH_SAME_ADDR(ia); | | 1042 | NEXT_IA_WITH_SAME_ADDR(ia); |
1039 | | | 1043 | |
1040 | if (ia == NULL) { | | 1044 | if (ia == NULL) { |
1041 | IFP_TO_IA(ifp, ia); | | 1045 | IFP_TO_IA(ifp, ia); |
1042 | if (ia == NULL) { | | 1046 | if (ia == NULL) { |
1043 | ARP_STATINC(ARP_STAT_RCVNOINT); | | 1047 | ARP_STATINC(ARP_STAT_RCVNOINT); |
1044 | goto out; | | 1048 | goto out; |
1045 | } | | 1049 | } |
1046 | } | | 1050 | } |
1047 | } | | 1051 | } |
1048 | | | 1052 | |
1049 | myaddr = ia->ia_addr.sin_addr; | | 1053 | myaddr = ia->ia_addr.sin_addr; |
1050 | | | 1054 | |
1051 | /* XXX checks for bridge case? */ | | 1055 | /* XXX checks for bridge case? */ |
1052 | if (!memcmp(ar_sha(ah), CLLADDR(ifp->if_sadl), ifp->if_addrlen)) { | | 1056 | if (!memcmp(ar_sha(ah), CLLADDR(ifp->if_sadl), ifp->if_addrlen)) { |
1053 | ARP_STATINC(ARP_STAT_RCVLOCALSHA); | | 1057 | ARP_STATINC(ARP_STAT_RCVLOCALSHA); |
1054 | goto out; /* it's from me, ignore it. */ | | 1058 | goto out; /* it's from me, ignore it. */ |
1055 | } | | 1059 | } |
1056 | | | 1060 | |
1057 | /* XXX checks for bridge case? */ | | 1061 | /* XXX checks for bridge case? */ |
1058 | if (!memcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { | | 1062 | if (!memcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { |
1059 | ARP_STATINC(ARP_STAT_RCVBCASTSHA); | | 1063 | ARP_STATINC(ARP_STAT_RCVBCASTSHA); |
1060 | log(LOG_ERR, | | 1064 | log(LOG_ERR, |
1061 | "%s: arp: link address is broadcast for IP address %s!\n", | | 1065 | "%s: arp: link address is broadcast for IP address %s!\n", |
1062 | ifp->if_xname, in_fmtaddr(isaddr)); | | 1066 | ifp->if_xname, in_fmtaddr(isaddr)); |
1063 | goto out; | | 1067 | goto out; |
1064 | } | | 1068 | } |
1065 | | | 1069 | |
1066 | /* | | 1070 | /* |
1067 | * If the source IP address is zero, this is an RFC 5227 ARP probe | | 1071 | * If the source IP address is zero, this is an RFC 5227 ARP probe |
1068 | */ | | 1072 | */ |
1069 | if (in_nullhost(isaddr)) { | | 1073 | if (in_nullhost(isaddr)) { |
1070 | ARP_STATINC(ARP_STAT_RCVZEROSPA); | | 1074 | ARP_STATINC(ARP_STAT_RCVZEROSPA); |
1071 | goto reply; | | 1075 | goto reply; |
1072 | } | | 1076 | } |
1073 | | | 1077 | |
1074 | if (in_hosteq(isaddr, myaddr)) { | | 1078 | if (in_hosteq(isaddr, myaddr)) { |
1075 | ARP_STATINC(ARP_STAT_RCVLOCALSPA); | | 1079 | ARP_STATINC(ARP_STAT_RCVLOCALSPA); |
1076 | log(LOG_ERR, | | 1080 | log(LOG_ERR, |
1077 | "duplicate IP address %s sent from link address %s\n", | | 1081 | "duplicate IP address %s sent from link address %s\n", |
1078 | in_fmtaddr(isaddr), lla_snprintf(ar_sha(ah), ah->ar_hln)); | | 1082 | in_fmtaddr(isaddr), lla_snprintf(ar_sha(ah), ah->ar_hln)); |
1079 | itaddr = myaddr; | | 1083 | itaddr = myaddr; |
1080 | goto reply; | | 1084 | goto reply; |
1081 | } | | 1085 | } |
1082 | la = arplookup(m, &isaddr, in_hosteq(itaddr, myaddr), 0); | | 1086 | la = arplookup(m, &isaddr, in_hosteq(itaddr, myaddr), 0); |
1083 | if (la != NULL && (rt = la->la_rt) && (sdl = satosdl(rt->rt_gateway))) { | | 1087 | if (la != NULL && (rt = la->la_rt) && (sdl = satosdl(rt->rt_gateway))) { |
1084 | if (sdl->sdl_alen && | | 1088 | if (sdl->sdl_alen && |
1085 | memcmp(ar_sha(ah), CLLADDR(sdl), sdl->sdl_alen)) { | | 1089 | memcmp(ar_sha(ah), CLLADDR(sdl), sdl->sdl_alen)) { |
1086 | if (rt->rt_flags & RTF_STATIC) { | | 1090 | if (rt->rt_flags & RTF_STATIC) { |
1087 | ARP_STATINC(ARP_STAT_RCVOVERPERM); | | 1091 | ARP_STATINC(ARP_STAT_RCVOVERPERM); |
| | | 1092 | if (!log_permanent_modify) |
| | | 1093 | goto out; |
1088 | log(LOG_INFO, | | 1094 | log(LOG_INFO, |
1089 | "%s tried to overwrite permanent arp info" | | 1095 | "%s tried to overwrite permanent arp info" |
1090 | " for %s\n", | | 1096 | " for %s\n", |
1091 | lla_snprintf(ar_sha(ah), ah->ar_hln), | | 1097 | lla_snprintf(ar_sha(ah), ah->ar_hln), |
1092 | in_fmtaddr(isaddr)); | | 1098 | in_fmtaddr(isaddr)); |
1093 | goto out; | | 1099 | goto out; |
1094 | } else if (rt->rt_ifp != ifp) { | | 1100 | } else if (rt->rt_ifp != ifp) { |
1095 | ARP_STATINC(ARP_STAT_RCVOVERINT); | | 1101 | ARP_STATINC(ARP_STAT_RCVOVERINT); |
| | | 1102 | if (!log_wrong_iface) |
| | | 1103 | goto out; |
1096 | log(LOG_INFO, | | 1104 | log(LOG_INFO, |
1097 | "%s on %s tried to overwrite " | | 1105 | "%s on %s tried to overwrite " |
1098 | "arp info for %s on %s\n", | | 1106 | "arp info for %s on %s\n", |
1099 | lla_snprintf(ar_sha(ah), ah->ar_hln), | | 1107 | lla_snprintf(ar_sha(ah), ah->ar_hln), |
1100 | ifp->if_xname, in_fmtaddr(isaddr), | | 1108 | ifp->if_xname, in_fmtaddr(isaddr), |
1101 | rt->rt_ifp->if_xname); | | 1109 | rt->rt_ifp->if_xname); |
1102 | goto out; | | 1110 | goto out; |
1103 | } else { | | 1111 | } else { |
1104 | ARP_STATINC(ARP_STAT_RCVOVER); | | 1112 | ARP_STATINC(ARP_STAT_RCVOVER); |
1105 | log(LOG_INFO, | | 1113 | if (log_movements) |
1106 | "arp info overwritten for %s by %s\n", | | 1114 | log(LOG_INFO, "arp info overwritten " |
1107 | in_fmtaddr(isaddr), | | 1115 | "for %s by %s\n", |
1108 | lla_snprintf(ar_sha(ah), ah->ar_hln)); | | 1116 | in_fmtaddr(isaddr), |
| | | 1117 | lla_snprintf(ar_sha(ah), |
| | | 1118 | ah->ar_hln)); |
1109 | } | | 1119 | } |
1110 | } | | 1120 | } |
1111 | /* | | 1121 | /* |
1112 | * sanity check for the address length. | | 1122 | * sanity check for the address length. |
1113 | * XXX this does not work for protocols with variable address | | 1123 | * XXX this does not work for protocols with variable address |
1114 | * length. -is | | 1124 | * length. -is |
1115 | */ | | 1125 | */ |
1116 | if (sdl->sdl_alen && | | 1126 | if (sdl->sdl_alen && |
1117 | sdl->sdl_alen != ah->ar_hln) { | | 1127 | sdl->sdl_alen != ah->ar_hln) { |
1118 | ARP_STATINC(ARP_STAT_RCVLENCHG); | | 1128 | ARP_STATINC(ARP_STAT_RCVLENCHG); |
1119 | log(LOG_WARNING, | | 1129 | log(LOG_WARNING, |
1120 | "arp from %s: new addr len %d, was %d\n", | | 1130 | "arp from %s: new addr len %d, was %d\n", |
1121 | in_fmtaddr(isaddr), ah->ar_hln, sdl->sdl_alen); | | 1131 | in_fmtaddr(isaddr), ah->ar_hln, sdl->sdl_alen); |
1122 | } | | 1132 | } |
1123 | if (ifp->if_addrlen != ah->ar_hln) { | | 1133 | if (ifp->if_addrlen != ah->ar_hln) { |
1124 | ARP_STATINC(ARP_STAT_RCVBADLEN); | | 1134 | ARP_STATINC(ARP_STAT_RCVBADLEN); |
1125 | log(LOG_WARNING, | | 1135 | log(LOG_WARNING, |
1126 | "arp from %s: addr len: new %d, i/f %d (ignored)\n", | | 1136 | "arp from %s: addr len: new %d, i/f %d (ignored)\n", |
1127 | in_fmtaddr(isaddr), ah->ar_hln, | | 1137 | in_fmtaddr(isaddr), ah->ar_hln, |
1128 | ifp->if_addrlen); | | 1138 | ifp->if_addrlen); |
1129 | goto reply; | | 1139 | goto reply; |
1130 | } | | 1140 | } |
1131 | #if NTOKEN > 0 | | 1141 | #if NTOKEN > 0 |
1132 | /* | | 1142 | /* |
1133 | * XXX uses m_data and assumes the complete answer including | | 1143 | * XXX uses m_data and assumes the complete answer including |
1134 | * XXX token-ring headers is in the same buf | | 1144 | * XXX token-ring headers is in the same buf |
1135 | */ | | 1145 | */ |
1136 | if (ifp->if_type == IFT_ISO88025) { | | 1146 | if (ifp->if_type == IFT_ISO88025) { |
1137 | struct token_header *trh; | | 1147 | struct token_header *trh; |
1138 | | | 1148 | |
1139 | trh = (struct token_header *)M_TRHSTART(m); | | 1149 | trh = (struct token_header *)M_TRHSTART(m); |
1140 | if (trh->token_shost[0] & TOKEN_RI_PRESENT) { | | 1150 | if (trh->token_shost[0] & TOKEN_RI_PRESENT) { |
1141 | struct token_rif *rif; | | 1151 | struct token_rif *rif; |
1142 | size_t riflen; | | 1152 | size_t riflen; |
1143 | | | 1153 | |
1144 | rif = TOKEN_RIF(trh); | | 1154 | rif = TOKEN_RIF(trh); |
1145 | riflen = (ntohs(rif->tr_rcf) & | | 1155 | riflen = (ntohs(rif->tr_rcf) & |
1146 | TOKEN_RCF_LEN_MASK) >> 8; | | 1156 | TOKEN_RCF_LEN_MASK) >> 8; |
1147 | | | 1157 | |
1148 | if (riflen > 2 && | | 1158 | if (riflen > 2 && |
1149 | riflen < sizeof(struct token_rif) && | | 1159 | riflen < sizeof(struct token_rif) && |
1150 | (riflen & 1) == 0) { | | 1160 | (riflen & 1) == 0) { |
1151 | rif->tr_rcf ^= htons(TOKEN_RCF_DIRECTION); | | 1161 | rif->tr_rcf ^= htons(TOKEN_RCF_DIRECTION); |
1152 | rif->tr_rcf &= htons(~TOKEN_RCF_BROADCAST_MASK); | | 1162 | rif->tr_rcf &= htons(~TOKEN_RCF_BROADCAST_MASK); |
1153 | memcpy(TOKEN_RIF(la), rif, riflen); | | 1163 | memcpy(TOKEN_RIF(la), rif, riflen); |
1154 | } | | 1164 | } |
1155 | } | | 1165 | } |
1156 | } | | 1166 | } |
1157 | #endif /* NTOKEN > 0 */ | | 1167 | #endif /* NTOKEN > 0 */ |
1158 | (void)sockaddr_dl_setaddr(sdl, sdl->sdl_len, ar_sha(ah), | | 1168 | (void)sockaddr_dl_setaddr(sdl, sdl->sdl_len, ar_sha(ah), |
1159 | ah->ar_hln); | | 1169 | ah->ar_hln); |
1160 | if (rt->rt_expire) | | 1170 | if (rt->rt_expire) |
1161 | rt->rt_expire = time_second + arpt_keep; | | 1171 | rt->rt_expire = time_second + arpt_keep; |
1162 | rt->rt_flags &= ~RTF_REJECT; | | 1172 | rt->rt_flags &= ~RTF_REJECT; |
1163 | la->la_asked = 0; | | 1173 | la->la_asked = 0; |
1164 | | | 1174 | |
1165 | s = splnet(); | | 1175 | s = splnet(); |
1166 | mold = la->la_hold; | | 1176 | mold = la->la_hold; |
1167 | la->la_hold = 0; | | 1177 | la->la_hold = 0; |
1168 | splx(s); | | 1178 | splx(s); |
1169 | | | 1179 | |
1170 | if (mold) { | | 1180 | if (mold) { |
1171 | ARP_STATINC(ARP_STAT_DFRSENT); | | 1181 | ARP_STATINC(ARP_STAT_DFRSENT); |
1172 | (*ifp->if_output)(ifp, mold, rt_getkey(rt), rt); | | 1182 | (*ifp->if_output)(ifp, mold, rt_getkey(rt), rt); |
1173 | } | | 1183 | } |
1174 | } | | 1184 | } |
1175 | reply: | | 1185 | reply: |
1176 | if (op != ARPOP_REQUEST) { | | 1186 | if (op != ARPOP_REQUEST) { |
1177 | if (op == ARPOP_REPLY) | | 1187 | if (op == ARPOP_REPLY) |
1178 | ARP_STATINC(ARP_STAT_RCVREPLY); | | 1188 | ARP_STATINC(ARP_STAT_RCVREPLY); |
1179 | out: | | 1189 | out: |
1180 | m_freem(m); | | 1190 | m_freem(m); |
1181 | return; | | 1191 | return; |
1182 | } | | 1192 | } |
1183 | ARP_STATINC(ARP_STAT_RCVREQUEST); | | 1193 | ARP_STATINC(ARP_STAT_RCVREQUEST); |
1184 | if (in_hosteq(itaddr, myaddr)) { | | 1194 | if (in_hosteq(itaddr, myaddr)) { |
1185 | /* I am the target */ | | 1195 | /* I am the target */ |
1186 | tha = ar_tha(ah); | | 1196 | tha = ar_tha(ah); |
1187 | if (tha) | | 1197 | if (tha) |
1188 | memcpy(tha, ar_sha(ah), ah->ar_hln); | | 1198 | memcpy(tha, ar_sha(ah), ah->ar_hln); |
1189 | memcpy(ar_sha(ah), CLLADDR(ifp->if_sadl), ah->ar_hln); | | 1199 | memcpy(ar_sha(ah), CLLADDR(ifp->if_sadl), ah->ar_hln); |
1190 | } else { | | 1200 | } else { |
1191 | la = arplookup(m, &itaddr, 0, SIN_PROXY); | | 1201 | la = arplookup(m, &itaddr, 0, SIN_PROXY); |
1192 | if (la == NULL) | | 1202 | if (la == NULL) |
1193 | goto out; | | 1203 | goto out; |
1194 | rt = la->la_rt; | | 1204 | rt = la->la_rt; |
1195 | if (rt->rt_ifp->if_type == IFT_CARP && | | 1205 | if (rt->rt_ifp->if_type == IFT_CARP && |
1196 | m->m_pkthdr.rcvif->if_type != IFT_CARP) | | 1206 | m->m_pkthdr.rcvif->if_type != IFT_CARP) |
1197 | goto out; | | 1207 | goto out; |
1198 | tha = ar_tha(ah); | | 1208 | tha = ar_tha(ah); |
1199 | if (tha) | | 1209 | if (tha) |
1200 | memcpy(tha, ar_sha(ah), ah->ar_hln); | | 1210 | memcpy(tha, ar_sha(ah), ah->ar_hln); |
1201 | sdl = satosdl(rt->rt_gateway); | | 1211 | sdl = satosdl(rt->rt_gateway); |
1202 | memcpy(ar_sha(ah), CLLADDR(sdl), ah->ar_hln); | | 1212 | memcpy(ar_sha(ah), CLLADDR(sdl), ah->ar_hln); |
1203 | } | | 1213 | } |
1204 | | | 1214 | |
1205 | memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); | | 1215 | memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); |
1206 | memcpy(ar_spa(ah), &itaddr, ah->ar_pln); | | 1216 | memcpy(ar_spa(ah), &itaddr, ah->ar_pln); |
1207 | ah->ar_op = htons(ARPOP_REPLY); | | 1217 | ah->ar_op = htons(ARPOP_REPLY); |
1208 | ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ | | 1218 | ah->ar_pro = htons(ETHERTYPE_IP); /* let's be sure! */ |
1209 | switch (ifp->if_type) { | | 1219 | switch (ifp->if_type) { |
1210 | case IFT_IEEE1394: | | 1220 | case IFT_IEEE1394: |
1211 | /* | | 1221 | /* |
1212 | * ieee1394 arp reply is broadcast | | 1222 | * ieee1394 arp reply is broadcast |
1213 | */ | | 1223 | */ |
1214 | m->m_flags &= ~M_MCAST; | | 1224 | m->m_flags &= ~M_MCAST; |
1215 | m->m_flags |= M_BCAST; | | 1225 | m->m_flags |= M_BCAST; |
1216 | m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + ah->ar_hln; | | 1226 | m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + ah->ar_hln; |
1217 | break; | | 1227 | break; |
1218 | | | 1228 | |
1219 | default: | | 1229 | default: |
1220 | m->m_flags &= ~(M_BCAST|M_MCAST); /* never reply by broadcast */ | | 1230 | m->m_flags &= ~(M_BCAST|M_MCAST); /* never reply by broadcast */ |
1221 | m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); | | 1231 | m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); |
1222 | break; | | 1232 | break; |
1223 | } | | 1233 | } |
1224 | m->m_pkthdr.len = m->m_len; | | 1234 | m->m_pkthdr.len = m->m_len; |
1225 | sa.sa_family = AF_ARP; | | 1235 | sa.sa_family = AF_ARP; |
1226 | sa.sa_len = 2; | | 1236 | sa.sa_len = 2; |
1227 | arps = ARP_STAT_GETREF(); | | 1237 | arps = ARP_STAT_GETREF(); |
1228 | arps[ARP_STAT_SNDTOTAL]++; | | 1238 | arps[ARP_STAT_SNDTOTAL]++; |
1229 | arps[ARP_STAT_SNDREPLY]++; | | 1239 | arps[ARP_STAT_SNDREPLY]++; |
1230 | ARP_STAT_PUTREF(); | | 1240 | ARP_STAT_PUTREF(); |
1231 | (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0); | | 1241 | (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0); |
1232 | return; | | 1242 | return; |
1233 | } | | 1243 | } |
1234 | | | 1244 | |
1235 | /* | | 1245 | /* |
1236 | * Free an arp entry. | | 1246 | * Free an arp entry. |
1237 | */ | | 1247 | */ |
1238 | static void arptfree(struct llinfo_arp *la) | | 1248 | static void arptfree(struct llinfo_arp *la) |
1239 | { | | 1249 | { |
1240 | struct rtentry *rt = la->la_rt; | | 1250 | struct rtentry *rt = la->la_rt; |
1241 | struct sockaddr_dl *sdl; | | 1251 | struct sockaddr_dl *sdl; |
1242 | | | 1252 | |
1243 | ARP_LOCK_CHECK(); | | 1253 | ARP_LOCK_CHECK(); |
1244 | | | 1254 | |
1245 | if (rt == NULL) | | 1255 | if (rt == NULL) |
1246 | panic("arptfree"); | | 1256 | panic("arptfree"); |
1247 | if (rt->rt_refcnt > 0 && (sdl = satosdl(rt->rt_gateway)) && | | 1257 | if (rt->rt_refcnt > 0 && (sdl = satosdl(rt->rt_gateway)) && |
1248 | sdl->sdl_family == AF_LINK) { | | 1258 | sdl->sdl_family == AF_LINK) { |
1249 | sdl->sdl_alen = 0; | | 1259 | sdl->sdl_alen = 0; |
1250 | la->la_asked = 0; | | 1260 | la->la_asked = 0; |
1251 | rt->rt_flags &= ~RTF_REJECT; | | 1261 | rt->rt_flags &= ~RTF_REJECT; |
1252 | return; | | 1262 | return; |
1253 | } | | 1263 | } |
1254 | rtrequest(RTM_DELETE, rt_getkey(rt), NULL, rt_mask(rt), 0, NULL); | | 1264 | rtrequest(RTM_DELETE, rt_getkey(rt), NULL, rt_mask(rt), 0, NULL); |
1255 | } | | 1265 | } |
1256 | | | 1266 | |
1257 | static struct llinfo_arp * | | 1267 | static struct llinfo_arp * |
1258 | arplookup(struct mbuf *m, const struct in_addr *addr, int create, int proxy) | | 1268 | arplookup(struct mbuf *m, const struct in_addr *addr, int create, int proxy) |
1259 | { | | 1269 | { |
1260 | return arplookup1(m, addr, create, proxy, NULL); | | 1270 | return arplookup1(m, addr, create, proxy, NULL); |
1261 | } | | 1271 | } |
1262 | | | 1272 | |
1263 | /* | | 1273 | /* |
1264 | * Lookup or enter a new address in arptab. | | 1274 | * Lookup or enter a new address in arptab. |
1265 | */ | | 1275 | */ |
1266 | static struct llinfo_arp * | | 1276 | static struct llinfo_arp * |
1267 | arplookup1(struct mbuf *m, const struct in_addr *addr, int create, int proxy, | | 1277 | arplookup1(struct mbuf *m, const struct in_addr *addr, int create, int proxy, |
1268 | struct rtentry *rt0) | | 1278 | struct rtentry *rt0) |
1269 | { | | 1279 | { |
1270 | struct arphdr *ah; | | 1280 | struct arphdr *ah; |
1271 | struct ifnet *ifp = m->m_pkthdr.rcvif; | | 1281 | struct ifnet *ifp = m->m_pkthdr.rcvif; |
1272 | struct rtentry *rt; | | 1282 | struct rtentry *rt; |
1273 | struct sockaddr_inarp sin; | | 1283 | struct sockaddr_inarp sin; |
1274 | const char *why = NULL; | | 1284 | const char *why = NULL; |
1275 | | | 1285 | |
1276 | ah = mtod(m, struct arphdr *); | | 1286 | ah = mtod(m, struct arphdr *); |
1277 | if (rt0 == NULL) { | | 1287 | if (rt0 == NULL) { |
1278 | memset(&sin, 0, sizeof(sin)); | | 1288 | memset(&sin, 0, sizeof(sin)); |
1279 | sin.sin_len = sizeof(sin); | | 1289 | sin.sin_len = sizeof(sin); |
1280 | sin.sin_family = AF_INET; | | 1290 | sin.sin_family = AF_INET; |
1281 | sin.sin_addr = *addr; | | 1291 | sin.sin_addr = *addr; |
1282 | sin.sin_other = proxy ? SIN_PROXY : 0; | | 1292 | sin.sin_other = proxy ? SIN_PROXY : 0; |
1283 | rt = rtalloc1(sintosa(&sin), create); | | 1293 | rt = rtalloc1(sintosa(&sin), create); |
1284 | if (rt == NULL) | | 1294 | if (rt == NULL) |
1285 | return NULL; | | 1295 | return NULL; |
1286 | rt->rt_refcnt--; | | 1296 | rt->rt_refcnt--; |
1287 | } else | | 1297 | } else |
1288 | rt = rt0; | | 1298 | rt = rt0; |
1289 | | | 1299 | |
1290 | #define IS_LLINFO(__rt) \ | | 1300 | #define IS_LLINFO(__rt) \ |
1291 | (((__rt)->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) == RTF_LLINFO && \ | | 1301 | (((__rt)->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) == RTF_LLINFO && \ |
1292 | (__rt)->rt_gateway->sa_family == AF_LINK) | | 1302 | (__rt)->rt_gateway->sa_family == AF_LINK) |
1293 | | | 1303 | |
1294 | | | 1304 | |
1295 | if (IS_LLINFO(rt)) | | 1305 | if (IS_LLINFO(rt)) |
1296 | return (struct llinfo_arp *)rt->rt_llinfo; | | 1306 | return (struct llinfo_arp *)rt->rt_llinfo; |
1297 | | | 1307 | |
1298 | if (create) { | | 1308 | if (create) { |
1299 | if (rt->rt_flags & RTF_GATEWAY) | | 1309 | if (rt->rt_flags & RTF_GATEWAY) |
1300 | why = "host is not on local network"; | | 1310 | why = "host is not on local network"; |
1301 | else if ((rt->rt_flags & RTF_LLINFO) == 0) { | | 1311 | else if ((rt->rt_flags & RTF_LLINFO) == 0) { |
1302 | ARP_STATINC(ARP_STAT_ALLOCFAIL); | | 1312 | ARP_STATINC(ARP_STAT_ALLOCFAIL); |
1303 | why = "could not allocate llinfo"; | | 1313 | why = "could not allocate llinfo"; |
1304 | } else | | 1314 | } else |
1305 | why = "gateway route is not ours"; | | 1315 | why = "gateway route is not ours"; |
1306 | log(LOG_DEBUG, "arplookup: unable to enter address" | | 1316 | log(LOG_DEBUG, "arplookup: unable to enter address" |
1307 | " for %s@%s on %s (%s)\n", | | 1317 | " for %s@%s on %s (%s)\n", |
1308 | in_fmtaddr(*addr), lla_snprintf(ar_sha(ah), ah->ar_hln), | | 1318 | in_fmtaddr(*addr), lla_snprintf(ar_sha(ah), ah->ar_hln), |
1309 | (ifp) ? ifp->if_xname : "null", why); | | 1319 | (ifp) ? ifp->if_xname : "null", why); |
1310 | if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_CLONED) != 0) { | | 1320 | if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_CLONED) != 0) { |
1311 | rtrequest(RTM_DELETE, rt_getkey(rt), | | 1321 | rtrequest(RTM_DELETE, rt_getkey(rt), |
1312 | rt->rt_gateway, rt_mask(rt), rt->rt_flags, NULL); | | 1322 | rt->rt_gateway, rt_mask(rt), rt->rt_flags, NULL); |
1313 | } | | 1323 | } |
1314 | } | | 1324 | } |
1315 | return NULL; | | 1325 | return NULL; |
1316 | } | | 1326 | } |
1317 | | | 1327 | |
1318 | int | | 1328 | int |
1319 | arpioctl(u_long cmd, void *data) | | 1329 | arpioctl(u_long cmd, void *data) |
1320 | { | | 1330 | { |
1321 | | | 1331 | |
1322 | return EOPNOTSUPP; | | 1332 | return EOPNOTSUPP; |
1323 | } | | 1333 | } |
1324 | | | 1334 | |
1325 | void | | 1335 | void |
1326 | arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) | | 1336 | arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) |
1327 | { | | 1337 | { |
1328 | struct in_addr *ip; | | 1338 | struct in_addr *ip; |
1329 | | | 1339 | |
1330 | /* | | 1340 | /* |
1331 | * Warn the user if another station has this IP address, | | 1341 | * Warn the user if another station has this IP address, |
1332 | * but only if the interface IP address is not zero. | | 1342 | * but only if the interface IP address is not zero. |
1333 | */ | | 1343 | */ |
1334 | ip = &IA_SIN(ifa)->sin_addr; | | 1344 | ip = &IA_SIN(ifa)->sin_addr; |
1335 | if (!in_nullhost(*ip)) | | 1345 | if (!in_nullhost(*ip)) |
1336 | arprequest(ifp, ip, ip, CLLADDR(ifp->if_sadl)); | | 1346 | arprequest(ifp, ip, ip, CLLADDR(ifp->if_sadl)); |
1337 | | | 1347 | |
1338 | ifa->ifa_rtrequest = arp_rtrequest; | | 1348 | ifa->ifa_rtrequest = arp_rtrequest; |
1339 | ifa->ifa_flags |= RTF_CLONING; | | 1349 | ifa->ifa_flags |= RTF_CLONING; |
1340 | } | | 1350 | } |
1341 | | | 1351 | |
1342 | /* | | 1352 | /* |
1343 | * Called from 10 Mb/s Ethernet interrupt handlers | | 1353 | * Called from 10 Mb/s Ethernet interrupt handlers |
1344 | * when ether packet type ETHERTYPE_REVARP | | 1354 | * when ether packet type ETHERTYPE_REVARP |
1345 | * is received. Common length and type checks are done here, | | 1355 | * is received. Common length and type checks are done here, |
1346 | * then the protocol-specific routine is called. | | 1356 | * then the protocol-specific routine is called. |
1347 | */ | | 1357 | */ |
1348 | void | | 1358 | void |
1349 | revarpinput(struct mbuf *m) | | 1359 | revarpinput(struct mbuf *m) |
1350 | { | | 1360 | { |
1351 | struct arphdr *ar; | | 1361 | struct arphdr *ar; |
1352 | | | 1362 | |
1353 | if (m->m_len < sizeof(struct arphdr)) | | 1363 | if (m->m_len < sizeof(struct arphdr)) |
1354 | goto out; | | 1364 | goto out; |
1355 | ar = mtod(m, struct arphdr *); | | 1365 | ar = mtod(m, struct arphdr *); |
1356 | #if 0 /* XXX I don't think we need this... and it will prevent other LL */ | | 1366 | #if 0 /* XXX I don't think we need this... and it will prevent other LL */ |
1357 | if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) | | 1367 | if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) |
1358 | goto out; | | 1368 | goto out; |
1359 | #endif | | 1369 | #endif |
1360 | if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) | | 1370 | if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) |
1361 | goto out; | | 1371 | goto out; |
1362 | switch (ntohs(ar->ar_pro)) { | | 1372 | switch (ntohs(ar->ar_pro)) { |
1363 | case ETHERTYPE_IP: | | 1373 | case ETHERTYPE_IP: |
1364 | case ETHERTYPE_IPTRAILERS: | | 1374 | case ETHERTYPE_IPTRAILERS: |
1365 | in_revarpinput(m); | | 1375 | in_revarpinput(m); |
1366 | return; | | 1376 | return; |
1367 | | | 1377 | |
1368 | default: | | 1378 | default: |
1369 | break; | | 1379 | break; |
1370 | } | | 1380 | } |
1371 | out: | | 1381 | out: |
1372 | m_freem(m); | | 1382 | m_freem(m); |
1373 | } | | 1383 | } |
1374 | | | 1384 | |
1375 | /* | | 1385 | /* |
1376 | * RARP for Internet protocols on 10 Mb/s Ethernet. | | 1386 | * RARP for Internet protocols on 10 Mb/s Ethernet. |
1377 | * Algorithm is that given in RFC 903. | | 1387 | * Algorithm is that given in RFC 903. |
1378 | * We are only using for bootstrap purposes to get an ip address for one of | | 1388 | * We are only using for bootstrap purposes to get an ip address for one of |
1379 | * our interfaces. Thus we support no user-interface. | | 1389 | * our interfaces. Thus we support no user-interface. |
1380 | * | | 1390 | * |
1381 | * Since the contents of the RARP reply are specific to the interface that | | 1391 | * Since the contents of the RARP reply are specific to the interface that |
1382 | * sent the request, this code must ensure that they are properly associated. | | 1392 | * sent the request, this code must ensure that they are properly associated. |
1383 | * | | 1393 | * |
1384 | * Note: also supports ARP via RARP packets, per the RFC. | | 1394 | * Note: also supports ARP via RARP packets, per the RFC. |
1385 | */ | | 1395 | */ |
1386 | void | | 1396 | void |
1387 | in_revarpinput(struct mbuf *m) | | 1397 | in_revarpinput(struct mbuf *m) |
1388 | { | | 1398 | { |
1389 | struct ifnet *ifp; | | 1399 | struct ifnet *ifp; |
1390 | struct arphdr *ah; | | 1400 | struct arphdr *ah; |
1391 | void *tha; | | 1401 | void *tha; |
1392 | int op; | | 1402 | int op; |
1393 | | | 1403 | |
1394 | ah = mtod(m, struct arphdr *); | | 1404 | ah = mtod(m, struct arphdr *); |
1395 | op = ntohs(ah->ar_op); | | 1405 | op = ntohs(ah->ar_op); |
1396 | | | 1406 | |
1397 | switch (m->m_pkthdr.rcvif->if_type) { | | 1407 | switch (m->m_pkthdr.rcvif->if_type) { |
1398 | case IFT_IEEE1394: | | 1408 | case IFT_IEEE1394: |
1399 | /* ARP without target hardware address is not supported */ | | 1409 | /* ARP without target hardware address is not supported */ |
1400 | goto out; | | 1410 | goto out; |
1401 | default: | | 1411 | default: |
1402 | break; | | 1412 | break; |
1403 | } | | 1413 | } |
1404 | | | 1414 | |
1405 | switch (op) { | | 1415 | switch (op) { |
1406 | case ARPOP_REQUEST: | | 1416 | case ARPOP_REQUEST: |
1407 | case ARPOP_REPLY: /* per RFC */ | | 1417 | case ARPOP_REPLY: /* per RFC */ |
1408 | in_arpinput(m); | | 1418 | in_arpinput(m); |
1409 | return; | | 1419 | return; |
1410 | case ARPOP_REVREPLY: | | 1420 | case ARPOP_REVREPLY: |
1411 | break; | | 1421 | break; |
1412 | case ARPOP_REVREQUEST: /* handled by rarpd(8) */ | | 1422 | case ARPOP_REVREQUEST: /* handled by rarpd(8) */ |
1413 | default: | | 1423 | default: |
1414 | goto out; | | 1424 | goto out; |
1415 | } | | 1425 | } |
1416 | if (!revarp_in_progress) | | 1426 | if (!revarp_in_progress) |
1417 | goto out; | | 1427 | goto out; |
1418 | ifp = m->m_pkthdr.rcvif; | | 1428 | ifp = m->m_pkthdr.rcvif; |
1419 | if (ifp != myip_ifp) /* !same interface */ | | 1429 | if (ifp != myip_ifp) /* !same interface */ |
1420 | goto out; | | 1430 | goto out; |
1421 | if (myip_initialized) | | 1431 | if (myip_initialized) |
1422 | goto wake; | | 1432 | goto wake; |
1423 | tha = ar_tha(ah); | | 1433 | tha = ar_tha(ah); |
1424 | if (tha == NULL) | | 1434 | if (tha == NULL) |
1425 | goto out; | | 1435 | goto out; |
1426 | if (memcmp(tha, CLLADDR(ifp->if_sadl), ifp->if_sadl->sdl_alen)) | | 1436 | if (memcmp(tha, CLLADDR(ifp->if_sadl), ifp->if_sadl->sdl_alen)) |
1427 | goto out; | | 1437 | goto out; |
1428 | memcpy(&srv_ip, ar_spa(ah), sizeof(srv_ip)); | | 1438 | memcpy(&srv_ip, ar_spa(ah), sizeof(srv_ip)); |
1429 | memcpy(&myip, ar_tpa(ah), sizeof(myip)); | | 1439 | memcpy(&myip, ar_tpa(ah), sizeof(myip)); |
1430 | myip_initialized = 1; | | 1440 | myip_initialized = 1; |
1431 | wake: /* Do wakeup every time in case it was missed. */ | | 1441 | wake: /* Do wakeup every time in case it was missed. */ |
1432 | wakeup((void *)&myip); | | 1442 | wakeup((void *)&myip); |
1433 | | | 1443 | |
1434 | out: | | 1444 | out: |
1435 | m_freem(m); | | 1445 | m_freem(m); |
1436 | } | | 1446 | } |
1437 | | | 1447 | |
1438 | /* | | 1448 | /* |
1439 | * Send a RARP request for the ip address of the specified interface. | | 1449 | * Send a RARP request for the ip address of the specified interface. |
1440 | * The request should be RFC 903-compliant. | | 1450 | * The request should be RFC 903-compliant. |
1441 | */ | | 1451 | */ |
1442 | void | | 1452 | void |
1443 | revarprequest(struct ifnet *ifp) | | 1453 | revarprequest(struct ifnet *ifp) |
1444 | { | | 1454 | { |
1445 | struct sockaddr sa; | | 1455 | struct sockaddr sa; |
1446 | struct mbuf *m; | | 1456 | struct mbuf *m; |
1447 | struct arphdr *ah; | | 1457 | struct arphdr *ah; |
1448 | void *tha; | | 1458 | void *tha; |
1449 | | | 1459 | |
1450 | if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) | | 1460 | if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) |
1451 | return; | | 1461 | return; |
1452 | MCLAIM(m, &arpdomain.dom_mowner); | | 1462 | MCLAIM(m, &arpdomain.dom_mowner); |
1453 | m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) + | | 1463 | m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) + |
1454 | 2*ifp->if_addrlen; | | 1464 | 2*ifp->if_addrlen; |
1455 | m->m_pkthdr.len = m->m_len; | | 1465 | m->m_pkthdr.len = m->m_len; |
1456 | MH_ALIGN(m, m->m_len); | | 1466 | MH_ALIGN(m, m->m_len); |
1457 | ah = mtod(m, struct arphdr *); | | 1467 | ah = mtod(m, struct arphdr *); |
1458 | memset(ah, 0, m->m_len); | | 1468 | memset(ah, 0, m->m_len); |
1459 | ah->ar_pro = htons(ETHERTYPE_IP); | | 1469 | ah->ar_pro = htons(ETHERTYPE_IP); |
1460 | ah->ar_hln = ifp->if_addrlen; /* hardware address length */ | | 1470 | ah->ar_hln = ifp->if_addrlen; /* hardware address length */ |
1461 | ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ | | 1471 | ah->ar_pln = sizeof(struct in_addr); /* protocol address length */ |
1462 | ah->ar_op = htons(ARPOP_REVREQUEST); | | 1472 | ah->ar_op = htons(ARPOP_REVREQUEST); |
1463 | | | 1473 | |
1464 | memcpy(ar_sha(ah), CLLADDR(ifp->if_sadl), ah->ar_hln); | | 1474 | memcpy(ar_sha(ah), CLLADDR(ifp->if_sadl), ah->ar_hln); |
1465 | tha = ar_tha(ah); | | 1475 | tha = ar_tha(ah); |
1466 | if (tha == NULL) | | 1476 | if (tha == NULL) |
1467 | return; | | 1477 | return; |
1468 | memcpy(tha, CLLADDR(ifp->if_sadl), ah->ar_hln); | | 1478 | memcpy(tha, CLLADDR(ifp->if_sadl), ah->ar_hln); |
1469 | | | 1479 | |
1470 | sa.sa_family = AF_ARP; | | 1480 | sa.sa_family = AF_ARP; |
1471 | sa.sa_len = 2; | | 1481 | sa.sa_len = 2; |
1472 | m->m_flags |= M_BCAST; | | 1482 | m->m_flags |= M_BCAST; |
1473 | (*ifp->if_output)(ifp, m, &sa, NULL); | | 1483 | (*ifp->if_output)(ifp, m, &sa, NULL); |
1474 | | | 1484 | |
1475 | } | | 1485 | } |
1476 | | | 1486 | |
1477 | /* | | 1487 | /* |
1478 | * RARP for the ip address of the specified interface, but also | | 1488 | * RARP for the ip address of the specified interface, but also |
1479 | * save the ip address of the server that sent the answer. | | 1489 | * save the ip address of the server that sent the answer. |
1480 | * Timeout if no response is received. | | 1490 | * Timeout if no response is received. |
1481 | */ | | 1491 | */ |
1482 | int | | 1492 | int |
1483 | revarpwhoarewe(struct ifnet *ifp, struct in_addr *serv_in, | | 1493 | revarpwhoarewe(struct ifnet *ifp, struct in_addr *serv_in, |
1484 | struct in_addr *clnt_in) | | 1494 | struct in_addr *clnt_in) |
1485 | { | | 1495 | { |
1486 | int result, count = 20; | | 1496 | int result, count = 20; |
1487 | | | 1497 | |
1488 | myip_initialized = 0; | | 1498 | myip_initialized = 0; |
1489 | myip_ifp = ifp; | | 1499 | myip_ifp = ifp; |
1490 | | | 1500 | |
1491 | revarp_in_progress = 1; | | 1501 | revarp_in_progress = 1; |
1492 | while (count--) { | | 1502 | while (count--) { |
1493 | revarprequest(ifp); | | 1503 | revarprequest(ifp); |
1494 | result = tsleep((void *)&myip, PSOCK, "revarp", hz/2); | | 1504 | result = tsleep((void *)&myip, PSOCK, "revarp", hz/2); |
1495 | if (result != EWOULDBLOCK) | | 1505 | if (result != EWOULDBLOCK) |
1496 | break; | | 1506 | break; |
1497 | } | | 1507 | } |
1498 | revarp_in_progress = 0; | | 1508 | revarp_in_progress = 0; |
1499 | | | 1509 | |
1500 | if (!myip_initialized) | | 1510 | if (!myip_initialized) |
1501 | return ENETUNREACH; | | 1511 | return ENETUNREACH; |
1502 | | | 1512 | |
1503 | memcpy(serv_in, &srv_ip, sizeof(*serv_in)); | | 1513 | memcpy(serv_in, &srv_ip, sizeof(*serv_in)); |
1504 | memcpy(clnt_in, &myip, sizeof(*clnt_in)); | | 1514 | memcpy(clnt_in, &myip, sizeof(*clnt_in)); |
1505 | return 0; | | 1515 | return 0; |
1506 | } | | 1516 | } |
1507 | | | 1517 | |
1508 | | | 1518 | |
1509 | | | 1519 | |
1510 | #ifdef DDB | | 1520 | #ifdef DDB |
1511 | | | 1521 | |
1512 | #include <machine/db_machdep.h> | | 1522 | #include <machine/db_machdep.h> |
1513 | #include <ddb/db_interface.h> | | 1523 | #include <ddb/db_interface.h> |
1514 | #include <ddb/db_output.h> | | 1524 | #include <ddb/db_output.h> |
1515 | | | 1525 | |
1516 | static void | | 1526 | static void |
1517 | db_print_sa(const struct sockaddr *sa) | | 1527 | db_print_sa(const struct sockaddr *sa) |
1518 | { | | 1528 | { |
1519 | int len; | | 1529 | int len; |
1520 | const u_char *p; | | 1530 | const u_char *p; |
1521 | | | 1531 | |
1522 | if (sa == NULL) { | | 1532 | if (sa == NULL) { |
1523 | db_printf("[NULL]"); | | 1533 | db_printf("[NULL]"); |
1524 | return; | | 1534 | return; |
1525 | } | | 1535 | } |
1526 | | | 1536 | |
1527 | p = (const u_char *)sa; | | 1537 | p = (const u_char *)sa; |
1528 | len = sa->sa_len; | | 1538 | len = sa->sa_len; |
1529 | db_printf("["); | | 1539 | db_printf("["); |
1530 | while (len > 0) { | | 1540 | while (len > 0) { |
1531 | db_printf("%d", *p); | | 1541 | db_printf("%d", *p); |
1532 | p++; len--; | | 1542 | p++; len--; |
1533 | if (len) db_printf(","); | | 1543 | if (len) db_printf(","); |
1534 | } | | 1544 | } |
1535 | db_printf("]\n"); | | 1545 | db_printf("]\n"); |
1536 | } | | 1546 | } |
1537 | | | 1547 | |
1538 | static void | | 1548 | static void |
1539 | db_print_ifa(struct ifaddr *ifa) | | 1549 | db_print_ifa(struct ifaddr *ifa) |
1540 | { | | 1550 | { |
1541 | if (ifa == NULL) | | 1551 | if (ifa == NULL) |
1542 | return; | | 1552 | return; |
1543 | db_printf(" ifa_addr="); | | 1553 | db_printf(" ifa_addr="); |
1544 | db_print_sa(ifa->ifa_addr); | | 1554 | db_print_sa(ifa->ifa_addr); |
1545 | db_printf(" ifa_dsta="); | | 1555 | db_printf(" ifa_dsta="); |
1546 | db_print_sa(ifa->ifa_dstaddr); | | 1556 | db_print_sa(ifa->ifa_dstaddr); |
1547 | db_printf(" ifa_mask="); | | 1557 | db_printf(" ifa_mask="); |
1548 | db_print_sa(ifa->ifa_netmask); | | 1558 | db_print_sa(ifa->ifa_netmask); |
1549 | db_printf(" flags=0x%x,refcnt=%d,metric=%d\n", | | 1559 | db_printf(" flags=0x%x,refcnt=%d,metric=%d\n", |
1550 | ifa->ifa_flags, | | 1560 | ifa->ifa_flags, |
1551 | ifa->ifa_refcnt, | | 1561 | ifa->ifa_refcnt, |
1552 | ifa->ifa_metric); | | 1562 | ifa->ifa_metric); |
1553 | } | | 1563 | } |
1554 | | | 1564 | |
1555 | static void | | 1565 | static void |
1556 | db_print_llinfo(void *li) | | 1566 | db_print_llinfo(void *li) |
1557 | { | | 1567 | { |
1558 | struct llinfo_arp *la; | | 1568 | struct llinfo_arp *la; |
1559 | | | 1569 | |
1560 | if (li == NULL) | | 1570 | if (li == NULL) |
1561 | return; | | 1571 | return; |
1562 | la = (struct llinfo_arp *)li; | | 1572 | la = (struct llinfo_arp *)li; |
1563 | db_printf(" la_rt=%p la_hold=%p, la_asked=0x%lx\n", | | 1573 | db_printf(" la_rt=%p la_hold=%p, la_asked=0x%lx\n", |
1564 | la->la_rt, la->la_hold, la->la_asked); | | 1574 | la->la_rt, la->la_hold, la->la_asked); |
1565 | } | | 1575 | } |
1566 | | | 1576 | |
1567 | /* | | 1577 | /* |
1568 | * Function to pass to rt_walktree(). | | 1578 | * Function to pass to rt_walktree(). |
1569 | * Return non-zero error to abort walk. | | 1579 | * Return non-zero error to abort walk. |
1570 | */ | | 1580 | */ |
1571 | static int | | 1581 | static int |
1572 | db_show_rtentry(struct rtentry *rt, void *w) | | 1582 | db_show_rtentry(struct rtentry *rt, void *w) |
1573 | { | | 1583 | { |
1574 | db_printf("rtentry=%p", rt); | | 1584 | db_printf("rtentry=%p", rt); |
1575 | | | 1585 | |
1576 | db_printf(" flags=0x%x refcnt=%d use=%"PRId64" expire=%"PRId64"\n", | | 1586 | db_printf(" flags=0x%x refcnt=%d use=%"PRId64" expire=%"PRId64"\n", |
1577 | rt->rt_flags, rt->rt_refcnt, | | 1587 | rt->rt_flags, rt->rt_refcnt, |
1578 | rt->rt_use, (uint64_t)rt->rt_expire); | | 1588 | rt->rt_use, (uint64_t)rt->rt_expire); |
1579 | | | 1589 | |
1580 | db_printf(" key="); db_print_sa(rt_getkey(rt)); | | 1590 | db_printf(" key="); db_print_sa(rt_getkey(rt)); |
1581 | db_printf(" mask="); db_print_sa(rt_mask(rt)); | | 1591 | db_printf(" mask="); db_print_sa(rt_mask(rt)); |
1582 | db_printf(" gw="); db_print_sa(rt->rt_gateway); | | 1592 | db_printf(" gw="); db_print_sa(rt->rt_gateway); |
1583 | | | 1593 | |
1584 | db_printf(" ifp=%p ", rt->rt_ifp); | | 1594 | db_printf(" ifp=%p ", rt->rt_ifp); |
1585 | if (rt->rt_ifp) | | 1595 | if (rt->rt_ifp) |
1586 | db_printf("(%s)", rt->rt_ifp->if_xname); | | 1596 | db_printf("(%s)", rt->rt_ifp->if_xname); |
1587 | else | | 1597 | else |
1588 | db_printf("(NULL)"); | | 1598 | db_printf("(NULL)"); |
1589 | | | 1599 | |
1590 | db_printf(" ifa=%p\n", rt->rt_ifa); | | 1600 | db_printf(" ifa=%p\n", rt->rt_ifa); |
1591 | db_print_ifa(rt->rt_ifa); | | 1601 | db_print_ifa(rt->rt_ifa); |
1592 | | | 1602 | |
1593 | db_printf(" gwroute=%p llinfo=%p\n", | | 1603 | db_printf(" gwroute=%p llinfo=%p\n", |
1594 | rt->rt_gwroute, rt->rt_llinfo); | | 1604 | rt->rt_gwroute, rt->rt_llinfo); |
1595 | db_print_llinfo(rt->rt_llinfo); | | 1605 | db_print_llinfo(rt->rt_llinfo); |
1596 | | | 1606 | |
1597 | return 0; | | 1607 | return 0; |
1598 | } | | 1608 | } |
1599 | | | 1609 | |
1600 | /* | | 1610 | /* |
1601 | * Function to print all the route trees. | | 1611 | * Function to print all the route trees. |
1602 | * Use this from ddb: "show arptab" | | 1612 | * Use this from ddb: "show arptab" |
1603 | */ | | 1613 | */ |
1604 | void | | 1614 | void |
1605 | db_show_arptab(db_expr_t addr, bool have_addr, | | 1615 | db_show_arptab(db_expr_t addr, bool have_addr, |
1606 | db_expr_t count, const char *modif) | | 1616 | db_expr_t count, const char *modif) |
1607 | { | | 1617 | { |
1608 | rt_walktree(AF_INET, db_show_rtentry, NULL); | | 1618 | rt_walktree(AF_INET, db_show_rtentry, NULL); |
1609 | } | | 1619 | } |
1610 | #endif | | 1620 | #endif |
1611 | | | 1621 | |
1612 | static int | | 1622 | static int |
1613 | sysctl_net_inet_arp_stats(SYSCTLFN_ARGS) | | 1623 | sysctl_net_inet_arp_stats(SYSCTLFN_ARGS) |
1614 | { | | 1624 | { |
1615 | | | 1625 | |
1616 | return NETSTAT_SYSCTL(arpstat_percpu, ARP_NSTATS); | | 1626 | return NETSTAT_SYSCTL(arpstat_percpu, ARP_NSTATS); |
1617 | } | | 1627 | } |
1618 | | | 1628 | |
1619 | static void | | 1629 | static void |
1620 | sysctl_net_inet_arp_setup(struct sysctllog **clog) | | 1630 | sysctl_net_inet_arp_setup(struct sysctllog **clog) |
1621 | { | | 1631 | { |
1622 | const struct sysctlnode *node; | | 1632 | const struct sysctlnode *node; |
1623 | | | 1633 | |
1624 | sysctl_createv(clog, 0, NULL, NULL, | | 1634 | sysctl_createv(clog, 0, NULL, NULL, |
1625 | CTLFLAG_PERMANENT, | | 1635 | CTLFLAG_PERMANENT, |
1626 | CTLTYPE_NODE, "net", NULL, | | 1636 | CTLTYPE_NODE, "net", NULL, |
1627 | NULL, 0, NULL, 0, | | 1637 | NULL, 0, NULL, 0, |
1628 | CTL_NET, CTL_EOL); | | 1638 | CTL_NET, CTL_EOL); |
1629 | sysctl_createv(clog, 0, NULL, NULL, | | 1639 | sysctl_createv(clog, 0, NULL, NULL, |
1630 | CTLFLAG_PERMANENT, | | 1640 | CTLFLAG_PERMANENT, |
1631 | CTLTYPE_NODE, "inet", NULL, | | 1641 | CTLTYPE_NODE, "inet", NULL, |
1632 | NULL, 0, NULL, 0, | | 1642 | NULL, 0, NULL, 0, |
1633 | CTL_NET, PF_INET, CTL_EOL); | | 1643 | CTL_NET, PF_INET, CTL_EOL); |
1634 | sysctl_createv(clog, 0, NULL, &node, | | 1644 | sysctl_createv(clog, 0, NULL, &node, |
1635 | CTLFLAG_PERMANENT, | | 1645 | CTLFLAG_PERMANENT, |
1636 | CTLTYPE_NODE, "arp", | | 1646 | CTLTYPE_NODE, "arp", |
1637 | SYSCTL_DESCR("Address Resolution Protocol"), | | 1647 | SYSCTL_DESCR("Address Resolution Protocol"), |
1638 | NULL, 0, NULL, 0, | | 1648 | NULL, 0, NULL, 0, |
1639 | CTL_NET, PF_INET, CTL_CREATE, CTL_EOL); | | 1649 | CTL_NET, PF_INET, CTL_CREATE, CTL_EOL); |
1640 | | | 1650 | |
1641 | sysctl_createv(clog, 0, NULL, NULL, | | 1651 | sysctl_createv(clog, 0, NULL, NULL, |
1642 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1652 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1643 | CTLTYPE_INT, "prune", | | 1653 | CTLTYPE_INT, "prune", |
1644 | SYSCTL_DESCR("ARP cache pruning interval"), | | 1654 | SYSCTL_DESCR("ARP cache pruning interval in seconds"), |
1645 | NULL, 0, &arpt_prune, 0, | | 1655 | NULL, 0, &arpt_prune, 0, |
1646 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); | | 1656 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); |
1647 | | | 1657 | |
1648 | sysctl_createv(clog, 0, NULL, NULL, | | 1658 | sysctl_createv(clog, 0, NULL, NULL, |
1649 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1659 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1650 | CTLTYPE_INT, "keep", | | 1660 | CTLTYPE_INT, "keep", |
1651 | SYSCTL_DESCR("Valid ARP entry lifetime"), | | 1661 | SYSCTL_DESCR("Valid ARP entry lifetime in seconds"), |
1652 | NULL, 0, &arpt_keep, 0, | | 1662 | NULL, 0, &arpt_keep, 0, |
1653 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); | | 1663 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); |
1654 | | | 1664 | |
1655 | sysctl_createv(clog, 0, NULL, NULL, | | 1665 | sysctl_createv(clog, 0, NULL, NULL, |
1656 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1666 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1657 | CTLTYPE_INT, "down", | | 1667 | CTLTYPE_INT, "down", |
1658 | SYSCTL_DESCR("Failed ARP entry lifetime"), | | 1668 | SYSCTL_DESCR("Failed ARP entry lifetime in seconds"), |
1659 | NULL, 0, &arpt_down, 0, | | 1669 | NULL, 0, &arpt_down, 0, |
1660 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); | | 1670 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); |
1661 | | | 1671 | |
1662 | sysctl_createv(clog, 0, NULL, NULL, | | 1672 | sysctl_createv(clog, 0, NULL, NULL, |
1663 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1673 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1664 | CTLTYPE_INT, "refresh", | | 1674 | CTLTYPE_INT, "refresh", |
1665 | SYSCTL_DESCR("ARP entry refresh interval"), | | 1675 | SYSCTL_DESCR("ARP entry refresh interval"), |
1666 | NULL, 0, &arpt_refresh, 0, | | 1676 | NULL, 0, &arpt_refresh, 0, |
1667 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); | | 1677 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); |
1668 | | | 1678 | |
1669 | sysctl_createv(clog, 0, NULL, NULL, | | 1679 | sysctl_createv(clog, 0, NULL, NULL, |
1670 | CTLFLAG_PERMANENT, | | 1680 | CTLFLAG_PERMANENT, |
1671 | CTLTYPE_STRUCT, "stats", | | 1681 | CTLTYPE_STRUCT, "stats", |
1672 | SYSCTL_DESCR("ARP statistics"), | | 1682 | SYSCTL_DESCR("ARP statistics"), |
1673 | sysctl_net_inet_arp_stats, 0, NULL, 0, | | 1683 | sysctl_net_inet_arp_stats, 0, NULL, 0, |
1674 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); | | 1684 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); |
| | | 1685 | |
| | | 1686 | sysctl_createv(clog, 0, NULL, NULL, |
| | | 1687 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| | | 1688 | CTLTYPE_INT, "log_movements", |
| | | 1689 | SYSCTL_DESCR("log ARP replies from MACs different than" |
| | | 1690 | " the one in the cache"), |
| | | 1691 | NULL, 0, &log_movements, 0, |
| | | 1692 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); |
| | | 1693 | |
| | | 1694 | sysctl_createv(clog, 0, NULL, NULL, |
| | | 1695 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| | | 1696 | CTLTYPE_INT, "log_permanent_modify", |
| | | 1697 | SYSCTL_DESCR("log ARP replies from MACs different than" |
| | | 1698 | " the one in the permanent arp entry"), |
| | | 1699 | NULL, 0, &log_permanent_modify, 0, |
| | | 1700 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); |
| | | 1701 | |
| | | 1702 | sysctl_createv(clog, 0, NULL, NULL, |
| | | 1703 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| | | 1704 | CTLTYPE_INT, "log_wrong_iface", |
| | | 1705 | SYSCTL_DESCR("log ARP packets arriving on the wrong" |
| | | 1706 | " interface"), |
| | | 1707 | NULL, 0, &log_wrong_iface, 0, |
| | | 1708 | CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); |
1675 | } | | 1709 | } |
1676 | | | 1710 | |
1677 | #endif /* INET */ | | 1711 | #endif /* INET */ |