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