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
50struct rwlock		 at_ifaddr_rw;
51struct at_ifaddrhead	 at_ifaddrhead;
52
53RW_SYSINIT(at_ifaddr_rw, &at_ifaddr_rw, "at_ifaddr_rw");
54
55static int aa_dorangeroute(struct ifaddr *ifa, u_int first, u_int last,
56	    int cmd);
57static int aa_addsingleroute(struct ifaddr *ifa, struct at_addr *addr,
58	    struct at_addr *mask);
59static int aa_delsingleroute(struct ifaddr *ifa, struct at_addr *addr,
60	    struct at_addr *mask);
61static int aa_dosingleroute(struct ifaddr *ifa, struct at_addr *addr,
62	    struct at_addr *mask, int cmd, int flags);
63static int at_scrub(struct ifnet *ifp, struct at_ifaddr *aa);
64static int at_ifinit(struct ifnet *ifp, struct at_ifaddr *aa,
65	    struct sockaddr_at *sat);
66static 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
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 *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
384out:
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 */
396static int
397at_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 */
426static int
427at_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 */
723int
724at_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
769static int
770aa_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
811static int
812aa_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
825static int
826aa_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
833static int
834aa_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
856static int
857aa_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