xref: /trueos/sys/netatalk/at_control.c (revision b4bc270e8f6757fa385861750ab22ba0ca4978ed)
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
9  * that both that copyright notice and this permission notice appear
10  * in supporting documentation, and that the name of The University
11  * of Michigan not be used in advertising or publicity pertaining to
12  * distribution of the software without specific, written prior
13  * permission. This software is supplied as is without expressed or
14  * implied warranties of any kind.
15  *
16  * This product includes software developed by the University of
17  * California, Berkeley and its contributors.
18  *
19  *	Research Systems Unix Group
20  *	The University of Michigan
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$");
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>
38 #include <sys/rwlock.h>
39 #include <sys/socket.h>
40 #include <net/if.h>
41 #include <net/route.h>
42 #include <netinet/in.h>
43 #undef s_net
44 #include <netinet/if_ether.h>
45 
46 #include <netatalk/at.h>
47 #include <netatalk/at_var.h>
48 #include <netatalk/at_extern.h>
49 
50 struct rwlock		 at_ifaddr_rw;
51 struct at_ifaddrhead	 at_ifaddrhead;
52 
53 RW_SYSINIT(at_ifaddr_rw, &at_ifaddr_rw, "at_ifaddr_rw");
54 
55 static int aa_dorangeroute(struct ifaddr *ifa, u_int first, u_int last,
56 	    int cmd);
57 static int aa_addsingleroute(struct ifaddr *ifa, struct at_addr *addr,
58 	    struct at_addr *mask);
59 static int aa_delsingleroute(struct ifaddr *ifa, struct at_addr *addr,
60 	    struct at_addr *mask);
61 static int aa_dosingleroute(struct ifaddr *ifa, struct at_addr *addr,
62 	    struct at_addr *mask, int cmd, int flags);
63 static int at_scrub(struct ifnet *ifp, struct at_ifaddr *aa);
64 static int at_ifinit(struct ifnet *ifp, struct at_ifaddr *aa,
65 	    struct sockaddr_at *sat);
66 static int aa_claim_addr(struct ifaddr *ifa, struct sockaddr *gw);
67 
68 #define	sateqaddr(a,b)							\
69 	((a)->sat_len == (b)->sat_len &&				\
70 	(a)->sat_family == (b)->sat_family &&				\
71 	(a)->sat_addr.s_net == (b)->sat_addr.s_net &&			\
72 	(a)->sat_addr.s_node == (b)->sat_addr.s_node)
73 
74 int
at_control(struct socket * so,u_long cmd,caddr_t data,struct ifnet * ifp,struct thread * td)75 at_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 *aa;
83 	struct ifaddr *ifa;
84 	int error;
85 
86 	/*
87 	 * If we have an ifp, then find the matching at_ifaddr if it exists
88 	 */
89 	aa = NULL;
90 	AT_IFADDR_RLOCK();
91 	if (ifp != NULL) {
92 		TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
93 			if (aa->aa_ifp == ifp)
94 				break;
95 		}
96 	}
97 	if (aa != NULL)
98 		ifa_ref(&aa->aa_ifa);
99 	AT_IFADDR_RUNLOCK();
100 
101 	/*
102 	 * In this first switch table we are basically getting ready for
103 	 * the second one, by getting the atalk-specific things set up
104 	 * so that they start to look more similar to other protocols etc.
105 	 */
106 	error = 0;
107 	switch (cmd) {
108 	case SIOCAIFADDR:
109 	case SIOCDIFADDR:
110 		/*
111 		 * If we have an appletalk sockaddr, scan forward of where we
112 		 * are now on the at_ifaddr list to find one with a matching
113 		 * address on this interface.  This may leave aa pointing to
114 		 * the first address on the NEXT interface!
115 		 */
116 		if (ifra->ifra_addr.sat_family == AF_APPLETALK) {
117 			struct at_ifaddr *oaa;
118 
119 			AT_IFADDR_RLOCK();
120 			for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
121 				if (aa->aa_ifp == ifp &&
122 				    sateqaddr(&aa->aa_addr, &ifra->ifra_addr))
123 					break;
124 			}
125 			if (oaa != NULL && oaa != aa)
126 				ifa_free(&oaa->aa_ifa);
127 			if (aa != NULL && oaa != aa)
128 				ifa_ref(&aa->aa_ifa);
129 			AT_IFADDR_RUNLOCK();
130 		}
131 		/*
132 		 * If we a retrying to delete an addres but didn't find such,
133 		 * then rewurn with an error
134 		 */
135 		if (cmd == SIOCDIFADDR && aa == NULL) {
136 			error = EADDRNOTAVAIL;
137 			goto out;
138 		}
139 		/*FALLTHROUGH*/
140 
141 	case SIOCSIFADDR:
142 		/*
143 		 * If we are not superuser, then we don't get to do these ops.
144 		 *
145 		 * XXXRW: Layering?
146 		 */
147 		if (priv_check(td, PRIV_NET_ADDIFADDR)) {
148 			error = EPERM;
149 			goto out;
150 		}
151 
152 		sat = satosat(&ifr->ifr_addr);
153 		nr = (struct netrange *)sat->sat_zero;
154 		if (nr->nr_phase == 1) {
155 			struct at_ifaddr *oaa;
156 
157 			/*
158 			 * Look for a phase 1 address on this interface.
159 			 * This may leave aa pointing to the first address on
160 			 * the NEXT interface!
161 			 */
162 			AT_IFADDR_RLOCK();
163 			for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
164 				if (aa->aa_ifp == ifp &&
165 				    (aa->aa_flags & AFA_PHASE2) == 0)
166 					break;
167 			}
168 			if (oaa != NULL && oaa != aa)
169 				ifa_free(&oaa->aa_ifa);
170 			if (aa != NULL && oaa != aa)
171 				ifa_ref(&aa->aa_ifa);
172 			AT_IFADDR_RUNLOCK();
173 		} else {		/* default to phase 2 */
174 			struct at_ifaddr *oaa;
175 
176 			/*
177 			 * Look for a phase 2 address on this interface.
178 			 * This may leave aa pointing to the first address on
179 			 * the NEXT interface!
180 			 */
181 			AT_IFADDR_RLOCK();
182 			for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
183 				if (aa->aa_ifp == ifp && (aa->aa_flags &
184 				    AFA_PHASE2))
185 					break;
186 			}
187 			if (oaa != NULL && oaa != aa)
188 				ifa_free(&oaa->aa_ifa);
189 			if (aa != NULL && oaa != aa)
190 				ifa_ref(&aa->aa_ifa);
191 			AT_IFADDR_RUNLOCK();
192 		}
193 
194 		if (ifp == NULL)
195 			panic("at_control");
196 
197 		/*
198 		 * If we failed to find an existing at_ifaddr entry, then we
199 		 * allocate a fresh one.
200 		 */
201 		if (aa == NULL) {
202 			aa = malloc(sizeof(struct at_ifaddr), M_IFADDR,
203 			    M_NOWAIT | M_ZERO);
204 			if (aa == NULL) {
205 				error = ENOBUFS;
206 				goto out;
207 			}
208 			callout_init(&aa->aa_callout, CALLOUT_MPSAFE);
209 
210 			ifa = (struct ifaddr *)aa;
211 			ifa_init(ifa);
212 
213 			/*
214 			 * As the at_ifaddr contains the actual sockaddrs,
215 			 * and the ifaddr itself, link them all together
216 			 * correctly.
217 			 */
218 			ifa->ifa_addr = (struct sockaddr *)&aa->aa_addr;
219 			ifa->ifa_dstaddr = (struct sockaddr *)&aa->aa_addr;
220 			ifa->ifa_netmask = (struct sockaddr *)&aa->aa_netmask;
221 
222 			/*
223 			 * Set/clear the phase 2 bit.
224 			 */
225 			if (nr->nr_phase == 1)
226 				aa->aa_flags &= ~AFA_PHASE2;
227 			else
228 				aa->aa_flags |= AFA_PHASE2;
229 
230 			ifa_ref(&aa->aa_ifa);		/* at_ifaddrhead */
231 			AT_IFADDR_WLOCK();
232 			if (!TAILQ_EMPTY(&at_ifaddrhead)) {
233 				/*
234 				 * Don't let the loopback be first, since the
235 				 * first address is the machine's default
236 				 * address for binding.  If it is, stick
237 				 * ourself in front, otherwise go to the back
238 				 * of the list.
239 				 */
240 				if (TAILQ_FIRST(&at_ifaddrhead)->aa_ifp->
241 				    if_flags & IFF_LOOPBACK)
242 					TAILQ_INSERT_HEAD(&at_ifaddrhead, aa,
243 					    aa_link);
244 				else
245 					TAILQ_INSERT_TAIL(&at_ifaddrhead, aa,
246 					    aa_link);
247 			} else
248 				TAILQ_INSERT_HEAD(&at_ifaddrhead, aa,
249 				    aa_link);
250 			AT_IFADDR_WUNLOCK();
251 
252 			/*
253 			 * and link it all together
254 			 */
255 			aa->aa_ifp = ifp;
256 			ifa_ref(&aa->aa_ifa);		/* if_addrhead */
257 			IF_ADDR_WLOCK(ifp);
258 			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
259 			IF_ADDR_WUNLOCK(ifp);
260 		} else {
261 			/*
262 			 * If we DID find one then we clobber any routes
263 			 * dependent on it..
264 			 */
265 			at_scrub(ifp, aa);
266 		}
267 		break;
268 
269 	case SIOCGIFADDR :
270 		sat = satosat(&ifr->ifr_addr);
271 		nr = (struct netrange *)sat->sat_zero;
272 		if (nr->nr_phase == 1) {
273 			struct at_ifaddr *oaa;
274 
275 			/*
276 			 * If the request is specifying phase 1, then
277 			 * only look at a phase one address
278 			 */
279 			AT_IFADDR_RLOCK();
280 			for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
281 				if (aa->aa_ifp == ifp &&
282 				    (aa->aa_flags & AFA_PHASE2) == 0)
283 					break;
284 			}
285 			if (oaa != NULL && oaa != aa)
286 				ifa_free(&oaa->aa_ifa);
287 			if (aa != NULL && oaa != aa)
288 				ifa_ref(&aa->aa_ifa);
289 			AT_IFADDR_RUNLOCK();
290 		} else {
291 			struct at_ifaddr *oaa;
292 
293 			/*
294 			 * default to phase 2
295 			 */
296 			AT_IFADDR_RLOCK();
297 			for (oaa = aa; aa; aa = TAILQ_NEXT(aa, aa_link)) {
298 				if (aa->aa_ifp == ifp && (aa->aa_flags &
299 				    AFA_PHASE2))
300 					break;
301 			}
302 			if (oaa != NULL && oaa != aa)
303 				ifa_free(&oaa->aa_ifa);
304 			if (aa != NULL && oaa != aa)
305 				ifa_ref(&aa->aa_ifa);
306 			AT_IFADDR_RUNLOCK();
307 		}
308 
309 		if (aa == NULL) {
310 			error = EADDRNOTAVAIL;
311 			goto out;
312 		}
313 		break;
314 	}
315 
316 	/*
317 	 * By the time this switch is run we should be able to assume that
318 	 * the "aa" pointer is valid when needed.
319 	 */
320 	switch (cmd) {
321 	case SIOCGIFADDR:
322 
323 		/*
324 		 * copy the contents of the sockaddr blindly.
325 		 */
326 		sat = (struct sockaddr_at *)&ifr->ifr_addr;
327 		*sat = aa->aa_addr;
328 
329  		/*
330 		 * and do some cleanups
331 		 */
332 		((struct netrange *)&sat->sat_zero)->nr_phase
333 		    = (aa->aa_flags & AFA_PHASE2) ? 2 : 1;
334 		((struct netrange *)&sat->sat_zero)->nr_firstnet =
335 		    aa->aa_firstnet;
336 		((struct netrange *)&sat->sat_zero)->nr_lastnet =
337 		    aa->aa_lastnet;
338 		break;
339 
340 	case SIOCSIFADDR:
341 		error = at_ifinit(ifp, aa,
342 		    (struct sockaddr_at *)&ifr->ifr_addr);
343 		goto out;
344 
345 	case SIOCAIFADDR:
346 		if (sateqaddr(&ifra->ifra_addr, &aa->aa_addr)) {
347 			error = 0;
348 			goto out;
349 		}
350 		error = at_ifinit(ifp, aa,
351 		    (struct sockaddr_at *)&ifr->ifr_addr);
352 		goto out;
353 
354 	case SIOCDIFADDR:
355 
356 		/*
357 		 * remove the ifaddr from the interface
358 		 */
359 		ifa = (struct ifaddr *)aa;
360 		IF_ADDR_WLOCK(ifp);
361 		TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
362 		IF_ADDR_WUNLOCK(ifp);
363 		ifa_free(ifa);				/* if_addrhead */
364 
365 		/*
366 		 * Now remove the at_ifaddr from the parallel structure
367 		 * as well, or we'd be in deep trouble
368 		 */
369 
370 		AT_IFADDR_WLOCK();
371 		TAILQ_REMOVE(&at_ifaddrhead, aa, aa_link);
372 		AT_IFADDR_WUNLOCK();
373 		ifa_free(ifa);				/* at_ifaddrhead */
374 		break;
375 
376 	default:
377 		if (ifp == NULL || ifp->if_ioctl == NULL) {
378 			error = EOPNOTSUPP;
379 			goto out;
380 		}
381 		error = ((*ifp->if_ioctl)(ifp, cmd, data));
382 	}
383 
384 out:
385 	if (aa != NULL)
386 		ifa_free(&aa->aa_ifa);
387 	return (error);
388 }
389 
390 /*
391  * Given an interface and an at_ifaddr (supposedly on that interface)
392  * remove  any routes that depend on this.
393  * Why ifp is needed I'm not sure,
394  * as aa->at_ifaddr.ifa_ifp should be the same.
395  */
396 static int
at_scrub(struct ifnet * ifp,struct at_ifaddr * aa)397 at_scrub(struct ifnet *ifp, struct at_ifaddr *aa)
398 {
399 	int error;
400 
401 	if (aa->aa_flags & AFA_ROUTE) {
402 		if (ifp->if_flags & IFF_LOOPBACK) {
403 			if ((error = aa_delsingleroute(&aa->aa_ifa,
404 			    &aa->aa_addr.sat_addr, &aa->aa_netmask.sat_addr))
405 			    != 0)
406 	    			return (error);
407 		} else if (ifp->if_flags & IFF_POINTOPOINT) {
408 			if ((error = rtinit(&aa->aa_ifa, RTM_DELETE,
409 			    RTF_HOST)) != 0)
410 	    			return (error);
411 		} else if (ifp->if_flags & IFF_BROADCAST) {
412 			error = aa_dorangeroute(&aa->aa_ifa,
413 			    ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet),
414 			    RTM_DELETE);
415 		}
416 		aa->aa_ifa.ifa_flags &= ~IFA_ROUTE;
417 		aa->aa_flags &= ~AFA_ROUTE;
418 	}
419 	return (0);
420 }
421 
422 /*
423  * given an at_ifaddr,a sockaddr_at and an ifp,
424  * bang them all together at high speed and see what happens
425  */
426 static int
at_ifinit(struct ifnet * ifp,struct at_ifaddr * aa,struct sockaddr_at * sat)427 at_ifinit(struct ifnet *ifp, struct at_ifaddr *aa, struct sockaddr_at *sat)
428 {
429 	struct netrange nr, onr;
430 	struct sockaddr_at oldaddr;
431 	int error = 0, i, j;
432 	int netinc, nodeinc, nnets;
433 	u_short net;
434 
435 	/*
436 	 * save the old addresses in the at_ifaddr just in case we need them.
437 	 */
438 	oldaddr = aa->aa_addr;
439 	onr.nr_firstnet = aa->aa_firstnet;
440 	onr.nr_lastnet = aa->aa_lastnet;
441 
442 	/*
443 	 * take the address supplied as an argument, and add it to the
444 	 * at_ifnet (also given). Remember ing to update
445 	 * those parts of the at_ifaddr that need special processing
446 	 */
447 	bzero(AA_SAT(aa), sizeof(struct sockaddr_at));
448 	bcopy(sat->sat_zero, &nr, sizeof(struct netrange));
449 	bcopy(sat->sat_zero, AA_SAT(aa)->sat_zero, sizeof(struct netrange));
450 	nnets = ntohs(nr.nr_lastnet) - ntohs(nr.nr_firstnet) + 1;
451 	aa->aa_firstnet = nr.nr_firstnet;
452 	aa->aa_lastnet = nr.nr_lastnet;
453 
454 /* XXX ALC */
455 #if 0
456 	printf("at_ifinit: %s: %u.%u range %u-%u phase %d\n",
457 	    ifp->if_name,
458 	    ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
459 	    ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet),
460 	    (aa->aa_flags & AFA_PHASE2) ? 2 : 1);
461 #endif
462 
463 	/*
464 	 * We could eliminate the need for a second phase 1 probe (post
465 	 * autoconf) if we check whether we're resetting the node. Note
466 	 * that phase 1 probes use only nodes, not net.node pairs.  Under
467 	 * phase 2, both the net and node must be the same.
468 	 */
469 	if (ifp->if_flags & IFF_LOOPBACK) {
470 		AA_SAT(aa)->sat_len = sat->sat_len;
471 		AA_SAT(aa)->sat_family = AF_APPLETALK;
472 		AA_SAT(aa)->sat_addr.s_net = sat->sat_addr.s_net;
473 		AA_SAT(aa)->sat_addr.s_node = sat->sat_addr.s_node;
474 #if 0
475 	} else if (fp->if_flags & IFF_POINTOPOINT) {
476 		/* unimplemented */
477 		/*
478 		 * we'd have to copy the dstaddr field over from the sat
479 		 * but it's not clear that it would contain the right info..
480 		 */
481 #endif
482 	} else {
483 		/*
484 		 * We are a normal (probably ethernet) interface.
485 		 * apply the new address to the interface structures etc.
486 		 * We will probe this address on the net first, before
487 		 * applying it to ensure that it is free.. If it is not, then
488 		 * we will try a number of other randomly generated addresses
489 		 * in this net and then increment the net.  etc.etc. until
490 		 * we find an unused address.
491 		 */
492 		aa->aa_flags |= AFA_PROBING; /* not loopback we Must probe? */
493 		AA_SAT(aa)->sat_len = sizeof(struct sockaddr_at);
494 		AA_SAT(aa)->sat_family = AF_APPLETALK;
495 		if (aa->aa_flags & AFA_PHASE2) {
496 			if (sat->sat_addr.s_net == ATADDR_ANYNET) {
497 				/*
498 				 * If we are phase 2, and the net was not
499 				 * specified then we select a random net
500 				 * within the supplied netrange.
501 				 * XXX use /dev/random?
502 				 */
503 				if (nnets != 1)
504 					net = ntohs(nr.nr_firstnet) +
505 					    time_second % (nnets - 1);
506 				else
507 					net = ntohs(nr.nr_firstnet);
508 			} else {
509 				/*
510 				 * if a net was supplied, then check that it
511 				 * is within the netrange. If it is not then
512 				 * replace the old values and return an error
513 				 */
514 				if (ntohs(sat->sat_addr.s_net) <
515 				    ntohs(nr.nr_firstnet) ||
516 				    ntohs(sat->sat_addr.s_net) >
517 				    ntohs(nr.nr_lastnet)) {
518 					aa->aa_addr = oldaddr;
519 					aa->aa_firstnet = onr.nr_firstnet;
520 					aa->aa_lastnet = onr.nr_lastnet;
521 					return (EINVAL);
522 				}
523 				/*
524 				 * otherwise just use the new net number..
525 				 */
526 				net = ntohs(sat->sat_addr.s_net);
527 			}
528 		} else {
529 			/*
530 			 * we must be phase one, so just use whatever we were
531 			 * given.  I guess it really isn't going to be
532 			 * used... RIGHT?
533 			 */
534 			net = ntohs(sat->sat_addr.s_net);
535 		}
536 
537 		/*
538 		 * set the node part of the address into the ifaddr.
539 		 * If it's not specified, be random about it...
540 		 * XXX use /dev/random?
541 		 */
542 		if (sat->sat_addr.s_node == ATADDR_ANYNODE)
543 			AA_SAT(aa)->sat_addr.s_node = time_second;
544 		else
545 			AA_SAT(aa)->sat_addr.s_node = sat->sat_addr.s_node;
546 
547 		/*
548 		 * Copy the phase.
549 		 */
550 		AA_SAT(aa)->sat_range.r_netrange.nr_phase =
551 		    ((aa->aa_flags & AFA_PHASE2) ? 2:1);
552 
553 		/*
554 		 * step through the nets in the range
555 		 * starting at the (possibly random) start point.
556 		 */
557 		for (i = nnets, netinc = 1; i > 0; net =
558 		    ntohs(nr.nr_firstnet) + ((net - ntohs(nr.nr_firstnet) +
559 		    netinc) % nnets), i--) {
560 			AA_SAT(aa)->sat_addr.s_net = htons(net);
561 
562 			/*
563 			 * using a rather strange stepping method,
564 			 * stagger through the possible node addresses
565 			 * Once again, starting at the (possibly random)
566 			 * initial node address.
567 			 */
568 			for (j = 0, nodeinc = time_second | 1; j < 256;
569 			    j++, AA_SAT(aa)->sat_addr.s_node += nodeinc) {
570 				if (AA_SAT(aa)->sat_addr.s_node > 253 ||
571 				    AA_SAT(aa)->sat_addr.s_node < 1)
572 					continue;
573 				aa->aa_probcnt = 10;
574 
575 				/*
576 				 * start off the probes as an asynchronous
577 				 * activity.  though why wait 200mSec?
578 				 */
579 				AARPTAB_LOCK();
580 				callout_reset(&aa->aa_callout, hz / 5,
581 				    aarpprobe, ifp);
582 				if (msleep(aa, &aarptab_mtx, PPAUSE|PCATCH,
583 				    "at_ifinit", 0)) {
584 					AARPTAB_UNLOCK();
585 					/*
586 					 * theoretically we shouldn't time
587 					 * out here so if we returned with an
588 					 * error..
589 					 */
590 					printf("at_ifinit: why did this "
591 					    "happen?!\n");
592 					aa->aa_addr = oldaddr;
593 					aa->aa_firstnet = onr.nr_firstnet;
594 					aa->aa_lastnet = onr.nr_lastnet;
595 					return (EINTR);
596 				}
597 				AARPTAB_UNLOCK();
598 
599 				/*
600 				 * The async activity should have woken us
601 				 * up.  We need to see if it was successful
602 				 * in finding a free spot, or if we need to
603 				 * iterate to the next address to try.
604 				 */
605 				if ((aa->aa_flags & AFA_PROBING) == 0)
606 					break;
607 			}
608 
609 			/*
610 			 * of course we need to break out through two loops...
611 			 */
612 			if ((aa->aa_flags & AFA_PROBING) == 0)
613 				break;
614 			/* reset node for next network */
615 			AA_SAT(aa)->sat_addr.s_node = time_second;
616 		}
617 
618 		/*
619 		 * if we are still trying to probe, then we have finished all
620 		 * the possible addresses, so we need to give up
621 		 */
622 		if (aa->aa_flags & AFA_PROBING) {
623 			aa->aa_addr = oldaddr;
624 			aa->aa_firstnet = onr.nr_firstnet;
625 			aa->aa_lastnet = onr.nr_lastnet;
626 			return (EADDRINUSE);
627 		}
628 	}
629 
630 	/*
631 	 * Now that we have selected an address, we need to tell the interface
632 	 * about it, just in case it needs to adjust something.
633 	 */
634 	if (ifp->if_ioctl != NULL &&
635 	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)aa))) {
636 		/*
637 		 * of course this could mean that it objects violently
638 		 * so if it does, we back out again..
639 		 */
640 		aa->aa_addr = oldaddr;
641 		aa->aa_firstnet = onr.nr_firstnet;
642 		aa->aa_lastnet = onr.nr_lastnet;
643 		return (error);
644 	}
645 
646 	/*
647 	 * set up the netmask part of the at_ifaddr
648 	 * and point the appropriate pointer in the ifaddr to it.
649 	 * probably pointless, but what the heck.. XXX
650 	 */
651 	bzero(&aa->aa_netmask, sizeof(aa->aa_netmask));
652 	aa->aa_netmask.sat_len = sizeof(struct sockaddr_at);
653 	aa->aa_netmask.sat_family = AF_APPLETALK;
654 	aa->aa_netmask.sat_addr.s_net = 0xffff;
655 	aa->aa_netmask.sat_addr.s_node = 0;
656 	aa->aa_ifa.ifa_netmask =(struct sockaddr *) &(aa->aa_netmask); /* XXX */
657 
658 	/*
659 	 * Initialize broadcast (or remote p2p) address
660 	 */
661 	bzero(&aa->aa_broadaddr, sizeof(aa->aa_broadaddr));
662 	aa->aa_broadaddr.sat_len = sizeof(struct sockaddr_at);
663 	aa->aa_broadaddr.sat_family = AF_APPLETALK;
664 
665 	aa->aa_ifa.ifa_metric = ifp->if_metric;
666 	if (ifp->if_flags & IFF_BROADCAST) {
667 		aa->aa_broadaddr.sat_addr.s_net = htons(0);
668 		aa->aa_broadaddr.sat_addr.s_node = 0xff;
669 		aa->aa_ifa.ifa_broadaddr = (struct sockaddr *)
670 		    &aa->aa_broadaddr;
671 		/* add the range of routes needed */
672 		error = aa_dorangeroute(&aa->aa_ifa, ntohs(aa->aa_firstnet),
673 		    ntohs(aa->aa_lastnet), RTM_ADD);
674 	} else if (ifp->if_flags & IFF_POINTOPOINT) {
675 		struct at_addr	rtaddr, rtmask;
676 
677 		bzero(&rtaddr, sizeof(rtaddr));
678 		bzero(&rtmask, sizeof(rtmask));
679 		/* fill in the far end if we know it here XXX */
680 		aa->aa_ifa.ifa_dstaddr = (struct sockaddr *) &aa->aa_dstaddr;
681 		error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask);
682 	} else if (ifp->if_flags & IFF_LOOPBACK) {
683 		struct at_addr	rtaddr, rtmask;
684 
685 		bzero(&rtaddr, sizeof(rtaddr));
686 		bzero(&rtmask, sizeof(rtmask));
687 		rtaddr.s_net = AA_SAT(aa)->sat_addr.s_net;
688 		rtaddr.s_node = AA_SAT(aa)->sat_addr.s_node;
689 		rtmask.s_net = 0xffff;
690 		 /* XXX should not be so.. should be HOST route */
691 		rtmask.s_node = 0x0;
692 		error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask);
693 	}
694 
695 	/*
696 	 * set the address of our "check if this addr is ours" routine.
697 	 */
698 	aa->aa_ifa.ifa_claim_addr = aa_claim_addr;
699 
700 	/*
701 	 * of course if we can't add these routes we back out, but it's
702 	 * getting risky by now XXX
703 	 */
704 	if (error) {
705 		at_scrub(ifp, aa);
706 		aa->aa_addr = oldaddr;
707 		aa->aa_firstnet = onr.nr_firstnet;
708 		aa->aa_lastnet = onr.nr_lastnet;
709 		return (error);
710 	}
711 
712 	/*
713 	 * note that the address has a route associated with it....
714 	 */
715 	aa->aa_ifa.ifa_flags |= IFA_ROUTE;
716 	aa->aa_flags |= AFA_ROUTE;
717 	return (0);
718 }
719 
720 /*
721  * check whether a given address is a broadcast address for us..
722  */
723 int
at_broadcast(const struct sockaddr_at * sat)724 at_broadcast(const struct sockaddr_at *sat)
725 {
726 	struct at_ifaddr *aa;
727 
728 	AT_IFADDR_LOCK_ASSERT();
729 
730 	/*
731 	 * If the node is not right, it can't be a broadcast
732 	 */
733 	if (sat->sat_addr.s_node != ATADDR_BCAST)
734 		return (0);
735 
736 	/*
737 	 * If the node was right then if the net is right, it's a broadcast
738 	 */
739 	if (sat->sat_addr.s_net == ATADDR_ANYNET)
740 		return (1);
741 
742 	/*
743 	 * failing that, if the net is one we have, it's a broadcast as well.
744 	 */
745 	TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
746 		if ((aa->aa_ifp->if_flags & IFF_BROADCAST)
747 		    && (ntohs(sat->sat_addr.s_net) >= ntohs(aa->aa_firstnet)
748 		    && ntohs(sat->sat_addr.s_net) <= ntohs(aa->aa_lastnet)))
749 			return (1);
750 	}
751 	return (0);
752 }
753 
754 /*
755  * aa_dorangeroute()
756  *
757  * Add a route for a range of networks from bot to top - 1.
758  * Algorithm:
759  *
760  * Split the range into two subranges such that the middle
761  * of the two ranges is the point where the highest bit of difference
762  * between the two addresses makes its transition.
763  * Each of the upper and lower ranges might not exist, or might be
764  * representable by 1 or more netmasks. In addition, if both
765  * ranges can be represented by the same netmask, then they can be merged
766  * by using the next higher netmask..
767  */
768 
769 static int
aa_dorangeroute(struct ifaddr * ifa,u_int bot,u_int top,int cmd)770 aa_dorangeroute(struct ifaddr *ifa, u_int bot, u_int top, int cmd)
771 {
772 	u_int mask1;
773 	struct at_addr addr;
774 	struct at_addr mask;
775 	int error;
776 
777 	/*
778 	 * slight sanity check
779 	 */
780 	if (bot > top) return (EINVAL);
781 
782 	addr.s_node = 0;
783 	mask.s_node = 0;
784 	/*
785 	 * just start out with the lowest boundary
786 	 * and keep extending the mask till it's too big.
787 	 */
788 
789 	 while (bot <= top) {
790 	 	mask1 = 1;
791 	 	while (((bot & ~mask1) >= bot) && ((bot | mask1) <= top)) {
792 			mask1 <<= 1;
793 			mask1 |= 1;
794 		}
795 		mask1 >>= 1;
796 		mask.s_net = htons(~mask1);
797 		addr.s_net = htons(bot);
798 		if (cmd == RTM_ADD) {
799 			error =	 aa_addsingleroute(ifa,&addr,&mask);
800 			if (error) {
801 				/* XXX clean up? */
802 				return (error);
803 			}
804 		} else
805 			error =	 aa_delsingleroute(ifa,&addr,&mask);
806 		bot = (bot | mask1) + 1;
807 	}
808 	return (0);
809 }
810 
811 static int
aa_addsingleroute(struct ifaddr * ifa,struct at_addr * addr,struct at_addr * mask)812 aa_addsingleroute(struct ifaddr *ifa, struct at_addr *addr,
813     struct at_addr *mask)
814 {
815 
816 #if 0
817 	printf("aa_addsingleroute: %x.%x mask %x.%x ...\n",
818 	    ntohs(addr->s_net), addr->s_node, ntohs(mask->s_net),
819 	    mask->s_node);
820 #endif
821 
822 	return (aa_dosingleroute(ifa, addr, mask, RTM_ADD, RTF_UP));
823 }
824 
825 static int
aa_delsingleroute(struct ifaddr * ifa,struct at_addr * addr,struct at_addr * mask)826 aa_delsingleroute(struct ifaddr *ifa, struct at_addr *addr,
827     struct at_addr *mask)
828 {
829 
830 	return (aa_dosingleroute(ifa, addr, mask, RTM_DELETE, 0));
831 }
832 
833 static int
aa_dosingleroute(struct ifaddr * ifa,struct at_addr * at_addr,struct at_addr * at_mask,int cmd,int flags)834 aa_dosingleroute(struct ifaddr *ifa, struct at_addr *at_addr,
835     struct at_addr *at_mask, int cmd, int flags)
836 {
837 	struct sockaddr_at addr, mask;
838 
839 	bzero(&addr, sizeof(addr));
840 	bzero(&mask, sizeof(mask));
841 	addr.sat_family = AF_APPLETALK;
842 	addr.sat_len = sizeof(struct sockaddr_at);
843 	addr.sat_addr.s_net = at_addr->s_net;
844 	addr.sat_addr.s_node = at_addr->s_node;
845 	mask.sat_family = AF_APPLETALK;
846 	mask.sat_len = sizeof(struct sockaddr_at);
847 	mask.sat_addr.s_net = at_mask->s_net;
848 	mask.sat_addr.s_node = at_mask->s_node;
849 	if (at_mask->s_node)
850 		flags |= RTF_HOST;
851 	return (rtrequest(cmd, (struct sockaddr *) &addr,
852 	    (flags & RTF_HOST)?(ifa->ifa_dstaddr):(ifa->ifa_addr),
853 	    (struct sockaddr *) &mask, flags, NULL));
854 }
855 
856 static int
aa_claim_addr(struct ifaddr * ifa,struct sockaddr * gw0)857 aa_claim_addr(struct ifaddr *ifa, struct sockaddr *gw0)
858 {
859 	struct sockaddr_at *addr = (struct sockaddr_at *)ifa->ifa_addr;
860 	struct sockaddr_at *gw = (struct sockaddr_at *)gw0;
861 
862 	switch (gw->sat_range.r_netrange.nr_phase) {
863 	case 1:
864 		if(addr->sat_range.r_netrange.nr_phase == 1)
865 			return (1);
866 
867 	case 0:
868 	case 2:
869 		/*
870 		 * if it's our net (including 0),
871 		 * or netranges are valid, and we are in the range,
872 		 * then it's ours.
873 		 */
874 		if ((addr->sat_addr.s_net == gw->sat_addr.s_net)
875 		    || ((addr->sat_range.r_netrange.nr_lastnet)
876 		    && (ntohs(gw->sat_addr.s_net) >=
877 		    ntohs(addr->sat_range.r_netrange.nr_firstnet))
878 		    && (ntohs(gw->sat_addr.s_net) <=
879 		    ntohs(addr->sat_range.r_netrange.nr_lastnet))))
880 			return (1);
881 		break;
882 	default:
883 		printf("atalk: bad phase\n");
884 	}
885 	return (0);
886 }
887