Deleted Added
full compact
at_control.c (194619) at_control.c (194819)
1/*-
2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
3 * Copyright (c) 2009 Robert N. M. Watson
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and distribute this software and
7 * its documentation for any purpose and without fee is hereby granted,
8 * provided that the above copyright notice appears in all copies and

--- 12 unchanged lines hidden (view full) ---

21 * c/o Wesley Craig
22 * 535 W. William Street
23 * Ann Arbor, Michigan
24 * +1-313-764-2278
25 * netatalk@umich.edu
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
3 * Copyright (c) 2009 Robert N. M. Watson
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and distribute this software and
7 * its documentation for any purpose and without fee is hereby granted,
8 * provided that the above copyright notice appears in all copies and

--- 12 unchanged lines hidden (view full) ---

21 * c/o Wesley Craig
22 * 535 W. William Street
23 * Ann Arbor, Michigan
24 * +1-313-764-2278
25 * netatalk@umich.edu
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/netatalk/at_control.c 194619 2009-06-22 10:23:54Z rwatson $");
29__FBSDID("$FreeBSD: head/sys/netatalk/at_control.c 194819 2009-06-24 10:32:44Z rwatson $");
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/sockio.h>
34#include <sys/lock.h>
35#include <sys/malloc.h>
36#include <sys/kernel.h>
37#include <sys/priv.h>

--- 36 unchanged lines hidden (view full) ---

74int
75at_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
76 struct thread *td)
77{
78 struct ifreq *ifr = (struct ifreq *)data;
79 struct sockaddr_at *sat;
80 struct netrange *nr;
81 struct at_aliasreq *ifra = (struct at_aliasreq *)data;
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/sockio.h>
34#include <sys/lock.h>
35#include <sys/malloc.h>
36#include <sys/kernel.h>
37#include <sys/priv.h>

--- 36 unchanged lines hidden (view full) ---

74int
75at_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
76 struct thread *td)
77{
78 struct ifreq *ifr = (struct ifreq *)data;
79 struct sockaddr_at *sat;
80 struct netrange *nr;
81 struct at_aliasreq *ifra = (struct at_aliasreq *)data;
82 struct at_ifaddr *aa0;
83 struct at_ifaddr *aa = NULL;
82 struct at_ifaddr *aa_temp;
83 struct at_ifaddr *aa;
84 struct ifaddr *ifa, *ifa0;
85 int error;
86
87 /*
88 * If we have an ifp, then find the matching at_ifaddr if it exists
89 */
84 struct ifaddr *ifa, *ifa0;
85 int error;
86
87 /*
88 * If we have an ifp, then find the matching at_ifaddr if it exists
89 */
90 AT_IFADDR_WLOCK();
90 aa = NULL;
91 AT_IFADDR_RLOCK();
91 if (ifp != NULL) {
92 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
93 if (aa->aa_ifp == ifp)
94 break;
95 }
96 }
92 if (ifp != NULL) {
93 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
94 if (aa->aa_ifp == ifp)
95 break;
96 }
97 }
98 if (aa != NULL)
99 ifa_ref(&aa->aa_ifa);
100 AT_IFADDR_RUNLOCK();
97
98 /*
99 * In this first switch table we are basically getting ready for
100 * the second one, by getting the atalk-specific things set up
101 * so that they start to look more similar to other protocols etc.
102 */
101
102 /*
103 * In this first switch table we are basically getting ready for
104 * the second one, by getting the atalk-specific things set up
105 * so that they start to look more similar to other protocols etc.
106 */
103
107 error = 0;
104 switch (cmd) {
105 case SIOCAIFADDR:
106 case SIOCDIFADDR:
107 /*
108 * If we have an appletalk sockaddr, scan forward of where we
109 * are now on the at_ifaddr list to find one with a matching
110 * address on this interface. This may leave aa pointing to
111 * the first address on the NEXT interface!
112 */
113 if (ifra->ifra_addr.sat_family == AF_APPLETALK) {
108 switch (cmd) {
109 case SIOCAIFADDR:
110 case SIOCDIFADDR:
111 /*
112 * If we have an appletalk sockaddr, scan forward of where we
113 * are now on the at_ifaddr list to find one with a matching
114 * address on this interface. This may leave aa pointing to
115 * the first address on the NEXT interface!
116 */
117 if (ifra->ifra_addr.sat_family == AF_APPLETALK) {
114 for (; aa; aa = aa->aa_next) {
118 struct at_ifaddr *oaa;
119
120 AT_IFADDR_RLOCK();
121 for (oaa = aa; aa; aa = aa->aa_next) {
115 if (aa->aa_ifp == ifp &&
116 sateqaddr(&aa->aa_addr, &ifra->ifra_addr))
117 break;
118 }
122 if (aa->aa_ifp == ifp &&
123 sateqaddr(&aa->aa_addr, &ifra->ifra_addr))
124 break;
125 }
126 if (oaa != NULL && oaa != aa)
127 ifa_free(&oaa->aa_ifa);
128 if (aa != NULL && oaa != aa)
129 ifa_ref(&aa->aa_ifa);
130 AT_IFADDR_RUNLOCK();
119 }
120 /*
121 * If we a retrying to delete an addres but didn't find such,
122 * then rewurn with an error
123 */
124 if (cmd == SIOCDIFADDR && aa == NULL) {
131 }
132 /*
133 * If we a retrying to delete an addres but didn't find such,
134 * then rewurn with an error
135 */
136 if (cmd == SIOCDIFADDR && aa == NULL) {
125 AT_IFADDR_WUNLOCK();
126 return (EADDRNOTAVAIL);
137 error = EADDRNOTAVAIL;
138 goto out;
127 }
128 /*FALLTHROUGH*/
129
130 case SIOCSIFADDR:
131 /*
132 * If we are not superuser, then we don't get to do these ops.
133 *
134 * XXXRW: Layering?
135 */
136 if (priv_check(td, PRIV_NET_ADDIFADDR)) {
139 }
140 /*FALLTHROUGH*/
141
142 case SIOCSIFADDR:
143 /*
144 * If we are not superuser, then we don't get to do these ops.
145 *
146 * XXXRW: Layering?
147 */
148 if (priv_check(td, PRIV_NET_ADDIFADDR)) {
137 AT_IFADDR_WUNLOCK();
138 return (EPERM);
149 error = EPERM;
150 goto out;
139 }
140
141 sat = satosat(&ifr->ifr_addr);
142 nr = (struct netrange *)sat->sat_zero;
143 if (nr->nr_phase == 1) {
151 }
152
153 sat = satosat(&ifr->ifr_addr);
154 nr = (struct netrange *)sat->sat_zero;
155 if (nr->nr_phase == 1) {
156 struct at_ifaddr *oaa;
157
144 /*
145 * Look for a phase 1 address on this interface.
146 * This may leave aa pointing to the first address on
147 * the NEXT interface!
148 */
158 /*
159 * Look for a phase 1 address on this interface.
160 * This may leave aa pointing to the first address on
161 * the NEXT interface!
162 */
149 for (; aa; aa = aa->aa_next) {
163 AT_IFADDR_RLOCK();
164 for (oaa = aa; aa; aa = aa->aa_next) {
150 if (aa->aa_ifp == ifp &&
151 (aa->aa_flags & AFA_PHASE2) == 0)
152 break;
153 }
165 if (aa->aa_ifp == ifp &&
166 (aa->aa_flags & AFA_PHASE2) == 0)
167 break;
168 }
169 if (oaa != NULL && oaa != aa)
170 ifa_free(&oaa->aa_ifa);
171 if (aa != NULL && oaa != aa)
172 ifa_ref(&aa->aa_ifa);
173 AT_IFADDR_RUNLOCK();
154 } else { /* default to phase 2 */
174 } else { /* default to phase 2 */
175 struct at_ifaddr *oaa;
176
155 /*
156 * Look for a phase 2 address on this interface.
157 * This may leave aa pointing to the first address on
158 * the NEXT interface!
159 */
177 /*
178 * Look for a phase 2 address on this interface.
179 * This may leave aa pointing to the first address on
180 * the NEXT interface!
181 */
160 for (; aa; aa = aa->aa_next) {
182 AT_IFADDR_RLOCK();
183 for (oaa = aa; aa; aa = aa->aa_next) {
161 if (aa->aa_ifp == ifp && (aa->aa_flags &
162 AFA_PHASE2))
163 break;
164 }
184 if (aa->aa_ifp == ifp && (aa->aa_flags &
185 AFA_PHASE2))
186 break;
187 }
188 if (oaa != NULL && oaa != aa)
189 ifa_free(&oaa->aa_ifa);
190 if (aa != NULL && oaa != aa)
191 ifa_ref(&aa->aa_ifa);
192 AT_IFADDR_RUNLOCK();
165 }
166
167 if (ifp == NULL)
168 panic("at_control");
169
170 /*
171 * If we failed to find an existing at_ifaddr entry, then we
172 * allocate a fresh one.
173 */
174 if (aa == NULL) {
193 }
194
195 if (ifp == NULL)
196 panic("at_control");
197
198 /*
199 * If we failed to find an existing at_ifaddr entry, then we
200 * allocate a fresh one.
201 */
202 if (aa == NULL) {
175 aa0 = malloc(sizeof(struct at_ifaddr), M_IFADDR,
203 aa = malloc(sizeof(struct at_ifaddr), M_IFADDR,
176 M_NOWAIT | M_ZERO);
204 M_NOWAIT | M_ZERO);
177 if (aa0 == NULL) {
178 AT_IFADDR_WUNLOCK();
179 return (ENOBUFS);
205 if (aa == NULL) {
206 error = ENOBUFS;
207 goto out;
180 }
208 }
181 callout_init(&aa0->aa_callout, CALLOUT_MPSAFE);
182 if ((aa = at_ifaddr_list) != NULL) {
183 /*
184 * Don't let the loopback be first, since the
185 * first address is the machine's default
186 * address for binding. If it is, stick
187 * ourself in front, otherwise go to the back
188 * of the list.
189 */
190 if (at_ifaddr_list->aa_ifp->if_flags &
191 IFF_LOOPBACK) {
192 aa = aa0;
193 aa->aa_next = at_ifaddr_list;
194 at_ifaddr_list = aa;
195 } else {
196 for (; aa->aa_next; aa = aa->aa_next)
197 ;
198 aa->aa_next = aa0;
199 }
200 } else
201 at_ifaddr_list = aa0;
202 aa = aa0;
209 callout_init(&aa->aa_callout, CALLOUT_MPSAFE);
203
210
204 /*
205 * Find the end of the interface's addresses
206 * and link our new one on the end
207 */
208 ifa = (struct ifaddr *)aa;
209 ifa_init(ifa);
210
211 /*
212 * As the at_ifaddr contains the actual sockaddrs,
211 ifa = (struct ifaddr *)aa;
212 ifa_init(ifa);
213
214 /*
215 * As the at_ifaddr contains the actual sockaddrs,
213 * and the ifaddr itself, link them al together
216 * and the ifaddr itself, link them all together
214 * correctly.
215 */
216 ifa->ifa_addr = (struct sockaddr *)&aa->aa_addr;
217 ifa->ifa_dstaddr = (struct sockaddr *)&aa->aa_addr;
218 ifa->ifa_netmask = (struct sockaddr *)&aa->aa_netmask;
219
220 /*
221 * Set/clear the phase 2 bit.
222 */
223 if (nr->nr_phase == 1)
224 aa->aa_flags &= ~AFA_PHASE2;
225 else
226 aa->aa_flags |= AFA_PHASE2;
227
217 * correctly.
218 */
219 ifa->ifa_addr = (struct sockaddr *)&aa->aa_addr;
220 ifa->ifa_dstaddr = (struct sockaddr *)&aa->aa_addr;
221 ifa->ifa_netmask = (struct sockaddr *)&aa->aa_netmask;
222
223 /*
224 * Set/clear the phase 2 bit.
225 */
226 if (nr->nr_phase == 1)
227 aa->aa_flags &= ~AFA_PHASE2;
228 else
229 aa->aa_flags |= AFA_PHASE2;
230
231 ifa_ref(&aa->aa_ifa); /* at_ifaddr_list */
232 AT_IFADDR_WLOCK();
233 if ((aa_temp = at_ifaddr_list) != NULL) {
234 /*
235 * Don't let the loopback be first, since the
236 * first address is the machine's default
237 * address for binding. If it is, stick
238 * ourself in front, otherwise go to the back
239 * of the list.
240 */
241 if (at_ifaddr_list->aa_ifp->if_flags &
242 IFF_LOOPBACK) {
243 aa->aa_next = at_ifaddr_list;
244 at_ifaddr_list = aa;
245 } else {
246 for (; aa_temp->aa_next; aa_temp =
247 aa_temp->aa_next)
248 ;
249 aa_temp->aa_next = aa;
250 }
251 } else
252 at_ifaddr_list = aa;
253 AT_IFADDR_WUNLOCK();
254
228 /*
229 * and link it all together
230 */
231 aa->aa_ifp = ifp;
255 /*
256 * and link it all together
257 */
258 aa->aa_ifp = ifp;
259 ifa_ref(&aa->aa_ifa); /* if_addrhead */
232 IF_ADDR_LOCK(ifp);
233 TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
234 IF_ADDR_UNLOCK(ifp);
235 } else {
236 /*
237 * If we DID find one then we clobber any routes
238 * dependent on it..
260 IF_ADDR_LOCK(ifp);
261 TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
262 IF_ADDR_UNLOCK(ifp);
263 } else {
264 /*
265 * If we DID find one then we clobber any routes
266 * dependent on it..
239 *
240 * XXXRW: While we ref the ifaddr, there are
241 * potential races here still.
242 */
267 */
243 ifa_ref(&aa->aa_ifa);
244 AT_IFADDR_WUNLOCK();
245 at_scrub(ifp, aa);
268 at_scrub(ifp, aa);
246 AT_IFADDR_WLOCK();
247 ifa_free(&aa->aa_ifa);
248 }
249 break;
250
251 case SIOCGIFADDR :
252 sat = satosat(&ifr->ifr_addr);
253 nr = (struct netrange *)sat->sat_zero;
254 if (nr->nr_phase == 1) {
269 }
270 break;
271
272 case SIOCGIFADDR :
273 sat = satosat(&ifr->ifr_addr);
274 nr = (struct netrange *)sat->sat_zero;
275 if (nr->nr_phase == 1) {
276 struct at_ifaddr *oaa;
277
255 /*
256 * If the request is specifying phase 1, then
257 * only look at a phase one address
258 */
278 /*
279 * If the request is specifying phase 1, then
280 * only look at a phase one address
281 */
259 for (; aa; aa = aa->aa_next) {
282 AT_IFADDR_RUNLOCK();
283 for (oaa = aa; aa; aa = aa->aa_next) {
260 if (aa->aa_ifp == ifp &&
261 (aa->aa_flags & AFA_PHASE2) == 0)
262 break;
263 }
284 if (aa->aa_ifp == ifp &&
285 (aa->aa_flags & AFA_PHASE2) == 0)
286 break;
287 }
288 if (oaa != NULL && oaa != aa)
289 ifa_free(&oaa->aa_ifa);
290 if (aa != NULL && oaa != aa)
291 ifa_ref(&aa->aa_ifa);
292 AT_IFADDR_RLOCK();
264 } else {
293 } else {
294 struct at_ifaddr *oaa;
295
265 /*
266 * default to phase 2
267 */
296 /*
297 * default to phase 2
298 */
268 for (; aa; aa = aa->aa_next) {
299 AT_IFADDR_RLOCK();
300 for (oaa = aa; aa; aa = aa->aa_next) {
269 if (aa->aa_ifp == ifp && (aa->aa_flags &
270 AFA_PHASE2))
271 break;
272 }
301 if (aa->aa_ifp == ifp && (aa->aa_flags &
302 AFA_PHASE2))
303 break;
304 }
305 if (oaa != NULL && oaa != aa)
306 ifa_free(&oaa->aa_ifa);
307 if (aa != NULL && oaa != aa)
308 ifa_ref(&aa->aa_ifa);
309 AT_IFADDR_RUNLOCK();
273 }
274
275 if (aa == NULL) {
310 }
311
312 if (aa == NULL) {
276 AT_IFADDR_WUNLOCK();
277 return (EADDRNOTAVAIL);
313 error = EADDRNOTAVAIL;
314 goto out;
278 }
279 break;
280 }
281
282 /*
283 * By the time this switch is run we should be able to assume that
284 * the "aa" pointer is valid when needed.
285 */

--- 10 unchanged lines hidden (view full) ---

296 * and do some cleanups
297 */
298 ((struct netrange *)&sat->sat_zero)->nr_phase
299 = (aa->aa_flags & AFA_PHASE2) ? 2 : 1;
300 ((struct netrange *)&sat->sat_zero)->nr_firstnet =
301 aa->aa_firstnet;
302 ((struct netrange *)&sat->sat_zero)->nr_lastnet =
303 aa->aa_lastnet;
315 }
316 break;
317 }
318
319 /*
320 * By the time this switch is run we should be able to assume that
321 * the "aa" pointer is valid when needed.
322 */

--- 10 unchanged lines hidden (view full) ---

333 * and do some cleanups
334 */
335 ((struct netrange *)&sat->sat_zero)->nr_phase
336 = (aa->aa_flags & AFA_PHASE2) ? 2 : 1;
337 ((struct netrange *)&sat->sat_zero)->nr_firstnet =
338 aa->aa_firstnet;
339 ((struct netrange *)&sat->sat_zero)->nr_lastnet =
340 aa->aa_lastnet;
304 AT_IFADDR_WUNLOCK();
305 break;
306
307 case SIOCSIFADDR:
341 break;
342
343 case SIOCSIFADDR:
308 ifa_ref(&aa->aa_ifa);
309 AT_IFADDR_WUNLOCK();
310 error = at_ifinit(ifp, aa,
311 (struct sockaddr_at *)&ifr->ifr_addr);
344 error = at_ifinit(ifp, aa,
345 (struct sockaddr_at *)&ifr->ifr_addr);
312 ifa_free(&aa->aa_ifa);
313 return (error);
346 goto out;
314
315 case SIOCAIFADDR:
316 if (sateqaddr(&ifra->ifra_addr, &aa->aa_addr)) {
347
348 case SIOCAIFADDR:
349 if (sateqaddr(&ifra->ifra_addr, &aa->aa_addr)) {
317 AT_IFADDR_WUNLOCK();
318 return (0);
350 error = 0;
351 goto out;
319 }
352 }
320 ifa_ref(&aa->aa_ifa);
321 AT_IFADDR_WUNLOCK();
322 error = at_ifinit(ifp, aa,
323 (struct sockaddr_at *)&ifr->ifr_addr);
353 error = at_ifinit(ifp, aa,
354 (struct sockaddr_at *)&ifr->ifr_addr);
324 ifa_free(&aa->aa_ifa);
325 return (error);
355 goto out;
326
327 case SIOCDIFADDR:
356
357 case SIOCDIFADDR:
358
328 /*
329 * remove the ifaddr from the interface
330 */
331 ifa0 = (struct ifaddr *)aa;
332 IF_ADDR_LOCK(ifp);
333 TAILQ_REMOVE(&ifp->if_addrhead, ifa0, ifa_link);
334 IF_ADDR_UNLOCK(ifp);
359 /*
360 * remove the ifaddr from the interface
361 */
362 ifa0 = (struct ifaddr *)aa;
363 IF_ADDR_LOCK(ifp);
364 TAILQ_REMOVE(&ifp->if_addrhead, ifa0, ifa_link);
365 IF_ADDR_UNLOCK(ifp);
366 ifa_free(ifa0); /* if_addrhead */
335
336 /*
337 * Now remove the at_ifaddr from the parallel structure
338 * as well, or we'd be in deep trouble
339 */
367
368 /*
369 * Now remove the at_ifaddr from the parallel structure
370 * as well, or we'd be in deep trouble
371 */
340 aa0 = aa;
341 if (aa0 == (aa = at_ifaddr_list)) {
372
373 AT_IFADDR_WLOCK();
374 if (aa == (aa_temp = at_ifaddr_list)) {
342 at_ifaddr_list = aa->aa_next;
343 } else {
375 at_ifaddr_list = aa->aa_next;
376 } else {
344 while (aa->aa_next && (aa->aa_next != aa0))
345 aa = aa->aa_next;
377 while (aa_temp->aa_next && (aa_temp->aa_next != aa))
378 aa_temp = aa_temp->aa_next;
346
347 /*
379
380 /*
348 * if we found it, remove it, otherwise we screwed up.
381 * if we found it, remove it, otherwise we
382 * screwed up.
349 */
383 */
350 if (aa->aa_next)
351 aa->aa_next = aa0->aa_next;
384 if (aa_temp->aa_next)
385 aa_temp->aa_next = aa->aa_next;
352 else
353 panic("at_control");
354 }
355 AT_IFADDR_WUNLOCK();
386 else
387 panic("at_control");
388 }
389 AT_IFADDR_WUNLOCK();
356
357 /*
358 * Now reclaim the reference.
359 */
360 ifa_free(ifa0);
390 ifa_free(ifa0); /* at_ifaddr_list */
391 aa = aa_temp;
361 break;
362
363 default:
392 break;
393
394 default:
364 AT_IFADDR_WUNLOCK();
365 if (ifp == NULL || ifp->if_ioctl == NULL)
366 return (EOPNOTSUPP);
367 return ((*ifp->if_ioctl)(ifp, cmd, data));
395 if (ifp == NULL || ifp->if_ioctl == NULL) {
396 error = EOPNOTSUPP;
397 goto out;
398 }
399 error = ((*ifp->if_ioctl)(ifp, cmd, data));
368 }
400 }
369 return (0);
401
402out:
403 if (aa != NULL)
404 ifa_free(&aa->aa_ifa);
405 return (error);
370}
371
372/*
373 * Given an interface and an at_ifaddr (supposedly on that interface)
374 * remove any routes that depend on this.
375 * Why ifp is needed I'm not sure,
376 * as aa->at_ifaddr.ifa_ifp should be the same.
377 */

--- 499 unchanged lines hidden ---
406}
407
408/*
409 * Given an interface and an at_ifaddr (supposedly on that interface)
410 * remove any routes that depend on this.
411 * Why ifp is needed I'm not sure,
412 * as aa->at_ifaddr.ifa_ifp should be the same.
413 */

--- 499 unchanged lines hidden ---