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
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
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
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
724 at_broadcast(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
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
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
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
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
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 }
Cache object: b2686a3f7c71b03882f0c1a455c0fd5d
|