xref: /freebsd/sys/netinet/sctp_bsd_addr.c (revision f0a75d274af375d15b97b830966b99a02b7db911)
1 /*-
2  * Copyright (c) 2001-2007, Cisco Systems, Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * a) Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  *
10  * b) Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *   the documentation and/or other materials provided with the distribution.
13  *
14  * c) Neither the name of Cisco Systems, Inc. nor the names of its
15  *    contributors may be used to endorse or promote products derived
16  *    from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $	 */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include <netinet/sctp_os.h>
37 #include <netinet/sctp_var.h>
38 #include <netinet/sctp_pcb.h>
39 #include <netinet/sctp_header.h>
40 #include <netinet/sctputil.h>
41 #include <netinet/sctp_output.h>
42 #include <netinet/sctp_bsd_addr.h>
43 #include <netinet/sctp_uio.h>
44 #include <netinet/sctputil.h>
45 #include <netinet/sctp_timer.h>
46 #include <netinet/sctp_asconf.h>
47 #include <netinet/sctp_indata.h>
48 #include <sys/unistd.h>
49 
50 #ifdef SCTP_DEBUG
51 extern uint32_t sctp_debug_on;
52 
53 #endif
54 
55 
56 #if defined(SCTP_USE_THREAD_BASED_ITERATOR)
57 void
58 sctp_wakeup_iterator(void)
59 {
60 	wakeup(&sctppcbinfo.iterator_running);
61 }
62 
63 static void
64 sctp_iterator_thread(void *v)
65 {
66 	SCTP_IPI_ITERATOR_WQ_LOCK();
67 	sctppcbinfo.iterator_running = 0;
68 	while (1) {
69 		msleep(&sctppcbinfo.iterator_running,
70 		    &sctppcbinfo.ipi_iterator_wq_mtx,
71 		    0, "waiting_for_work", 0);
72 		sctp_iterator_worker();
73 	}
74 }
75 
76 void
77 sctp_startup_iterator(void)
78 {
79 	int ret;
80 
81 	ret = kthread_create(sctp_iterator_thread,
82 	    (void *)NULL,
83 	    &sctppcbinfo.thread_proc,
84 	    RFPROC,
85 	    SCTP_KTHREAD_PAGES,
86 	    SCTP_KTRHEAD_NAME);
87 }
88 
89 #endif
90 
91 
92 void
93 sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa)
94 {
95 	struct in6_ifaddr *ifa6;
96 
97 	ifa6 = (struct in6_ifaddr *)ifa->ifa;
98 	ifa->flags = ifa6->ia6_flags;
99 	if (!ip6_use_deprecated) {
100 		if (ifa->flags &
101 		    IN6_IFF_DEPRECATED) {
102 			ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE;
103 		} else {
104 			ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
105 		}
106 	} else {
107 		ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
108 	}
109 	if (ifa->flags &
110 	    (IN6_IFF_DETACHED |
111 	    IN6_IFF_ANYCAST |
112 	    IN6_IFF_NOTREADY)) {
113 		ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE;
114 	} else {
115 		ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
116 	}
117 }
118 
119 
120 
121 static uint32_t
122 sctp_is_desired_interface_type(struct ifaddr *ifa)
123 {
124 	int result;
125 
126 	/* check the interface type to see if it's one we care about */
127 	switch (ifa->ifa_ifp->if_type) {
128 	case IFT_ETHER:
129 	case IFT_ISO88023:
130 	case IFT_ISO88024:
131 	case IFT_ISO88025:
132 	case IFT_ISO88026:
133 	case IFT_STARLAN:
134 	case IFT_P10:
135 	case IFT_P80:
136 	case IFT_HY:
137 	case IFT_FDDI:
138 	case IFT_XETHER:
139 	case IFT_ISDNBASIC:
140 	case IFT_ISDNPRIMARY:
141 	case IFT_PTPSERIAL:
142 	case IFT_PPP:
143 	case IFT_LOOP:
144 	case IFT_SLIP:
145 	case IFT_IP:
146 	case IFT_IPOVERCDLC:
147 	case IFT_IPOVERCLAW:
148 	case IFT_VIRTUALIPADDRESS:
149 		result = 1;
150 		break;
151 	default:
152 		result = 0;
153 	}
154 
155 	return (result);
156 }
157 
158 static void
159 sctp_init_ifns_for_vrf(int vrfid)
160 {
161 	/*
162 	 * Here we must apply ANY locks needed by the IFN we access and also
163 	 * make sure we lock any IFA that exists as we float through the
164 	 * list of IFA's
165 	 */
166 	struct ifnet *ifn;
167 	struct ifaddr *ifa;
168 	struct in6_ifaddr *ifa6;
169 	struct sctp_ifa *sctp_ifa;
170 	uint32_t ifa_flags;
171 
172 	TAILQ_FOREACH(ifn, &ifnet, if_list) {
173 		TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
174 			if (ifa->ifa_addr == NULL) {
175 				continue;
176 			}
177 			if ((ifa->ifa_addr->sa_family != AF_INET) &&
178 			    (ifa->ifa_addr->sa_family != AF_INET6)
179 			    ) {
180 				/* non inet/inet6 skip */
181 				continue;
182 			}
183 			if (ifa->ifa_addr->sa_family == AF_INET6) {
184 				ifa6 = (struct in6_ifaddr *)ifa;
185 				ifa_flags = ifa6->ia6_flags;
186 				if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
187 					/* skip unspecifed addresses */
188 					continue;
189 				}
190 			} else if (ifa->ifa_addr->sa_family == AF_INET) {
191 				if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
192 					continue;
193 				}
194 			}
195 			if (sctp_is_desired_interface_type(ifa) == 0) {
196 				/* non desired type */
197 				continue;
198 			}
199 			if ((ifa->ifa_addr->sa_family == AF_INET6) ||
200 			    (ifa->ifa_addr->sa_family == AF_INET)) {
201 				if (ifa->ifa_addr->sa_family == AF_INET6) {
202 					ifa6 = (struct in6_ifaddr *)ifa;
203 					ifa_flags = ifa6->ia6_flags;
204 				} else {
205 					ifa_flags = 0;
206 				}
207 				sctp_ifa = sctp_add_addr_to_vrf(vrfid,
208 				    (void *)ifn,
209 				    ifn->if_index,
210 				    ifn->if_type,
211 				    ifn->if_xname,
212 				    (void *)ifa,
213 				    ifa->ifa_addr,
214 				    ifa_flags
215 				    );
216 				if (sctp_ifa) {
217 					sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
218 				}
219 			}
220 		}
221 	}
222 }
223 
224 
225 void
226 sctp_init_vrf_list(int vrfid)
227 {
228 	if (vrfid > SCTP_MAX_VRF_ID)
229 		/* can't do that */
230 		return;
231 
232 	/* Don't care about return here */
233 	(void)sctp_allocate_vrf(vrfid);
234 
235 	/*
236 	 * Now we need to build all the ifn's for this vrf and there
237 	 * addresses
238 	 */
239 	sctp_init_ifns_for_vrf(vrfid);
240 }
241 
242 static uint8_t first_time = 0;
243 
244 
245 void
246 sctp_addr_change(struct ifaddr *ifa, int cmd)
247 {
248 	struct sctp_laddr *wi;
249 	struct sctp_ifa *ifap = NULL;
250 	uint32_t ifa_flags = 0;
251 	struct in6_ifaddr *ifa6;
252 
253 	/*
254 	 * BSD only has one VRF, if this changes we will need to hook in the
255 	 * right things here to get the id to pass to the address managment
256 	 * routine.
257 	 */
258 	if (first_time == 0) {
259 		/* Special test to see if my ::1 will showup with this */
260 		first_time = 1;
261 		sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID);
262 	}
263 	if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) {
264 		/* don't know what to do with this */
265 		return;
266 	}
267 	if (ifa->ifa_addr == NULL) {
268 		return;
269 	}
270 	if ((ifa->ifa_addr->sa_family != AF_INET) &&
271 	    (ifa->ifa_addr->sa_family != AF_INET6)
272 	    ) {
273 		/* non inet/inet6 skip */
274 		return;
275 	}
276 	if (ifa->ifa_addr->sa_family == AF_INET6) {
277 		ifa6 = (struct in6_ifaddr *)ifa;
278 		ifa_flags = ifa6->ia6_flags;
279 		if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
280 			/* skip unspecifed addresses */
281 			return;
282 		}
283 	} else if (ifa->ifa_addr->sa_family == AF_INET) {
284 		if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
285 			return;
286 		}
287 	}
288 	if (sctp_is_desired_interface_type(ifa) == 0) {
289 		/* non desired type */
290 		return;
291 	}
292 	if (cmd == RTM_ADD) {
293 		ifap = sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp,
294 		    ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type,
295 		    ifa->ifa_ifp->if_xname,
296 		    (void *)ifa, ifa->ifa_addr, ifa_flags);
297 		/*
298 		 * Bump up the refcount so that when the timer completes it
299 		 * will drop back down.
300 		 */
301 		if (ifap)
302 			atomic_add_int(&ifap->refcount, 1);
303 
304 	} else if (cmd == RTM_DELETE) {
305 
306 		ifap = sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, ifa->ifa_ifp->if_index);
307 		/*
308 		 * We don't bump refcount here so when it completes the
309 		 * final delete will happen.
310 		 */
311 	}
312 	if (ifap == NULL)
313 		return;
314 
315 	wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
316 	if (wi == NULL) {
317 		/*
318 		 * Gak, what can we do? We have lost an address change can
319 		 * you say HOSED?
320 		 */
321 #ifdef SCTP_DEBUG
322 		if (sctp_debug_on & SCTP_DEBUG_PCB1) {
323 			printf("Lost and address change ???\n");
324 		}
325 #endif				/* SCTP_DEBUG */
326 
327 		/* Opps, must decrement the count */
328 		sctp_free_ifa(ifap);
329 		return;
330 	}
331 	SCTP_INCR_LADDR_COUNT();
332 	bzero(wi, sizeof(*wi));
333 	wi->ifa = ifap;
334 	if (cmd == RTM_ADD) {
335 		wi->action = SCTP_ADD_IP_ADDRESS;
336 	} else if (cmd == RTM_DELETE) {
337 		wi->action = SCTP_DEL_IP_ADDRESS;
338 	}
339 	SCTP_IPI_ITERATOR_WQ_LOCK();
340 	/*
341 	 * Should this really be a tailq? As it is we will process the
342 	 * newest first :-0
343 	 */
344 	LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr);
345 	sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
346 	    (struct sctp_inpcb *)NULL,
347 	    (struct sctp_tcb *)NULL,
348 	    (struct sctp_nets *)NULL);
349 	SCTP_IPI_ITERATOR_WQ_UNLOCK();
350 }
351