2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
11 #include <sys/syslog.h>
12 #include <sys/types.h>
13 #include <sys/param.h>
14 #include <sys/socket.h>
15 #include <sys/ioctl.h>
17 #include <net/route.h>
18 #include <netatalk/endian.h>
19 #include <netatalk/at.h>
22 #include <sys/sockio.h>
25 #include <atalk/ddp.h>
26 #include <atalk/atp.h>
27 #include <atalk/rtmp.h>
29 #include "interface.h"
37 void rtmp_delzonemap(rtmp)
40 struct list *lz, *flz, *lr, *flr;
44 while ( lz ) { /* for each zone */
45 zt = (struct ziptab *)lz->l_data;
47 while ( lr ) { /* for each route */
48 if ( (struct rtmptab *)lr->l_data == rtmp ) {
49 if ( lr->l_prev == NULL ) { /* head */
50 if ( lr->l_next == NULL ) { /* last route in zone */
51 if ( zt->zt_prev == NULL ) {
54 zt->zt_prev->zt_next = zt->zt_next;
56 if ( zt->zt_next == NULL ) {
57 ziplast = zt->zt_prev;
59 zt->zt_next->zt_prev = zt->zt_prev;
65 zt->zt_rt = lr->l_next;
68 lr->l_prev->l_next = lr->l_next;
70 if ( lr->l_next != NULL ) {
71 lr->l_next->l_prev = lr->l_prev;
89 * Complete configuration for phase 1 interface using RTMP information.
91 static int rtmp_config( rh, iface )
93 struct interface *iface;
95 extern int stabletimer;
99 * If we're configuring a phase 2 interface, don't complete
100 * configuration with RTMP.
102 if ( iface->i_flags & IFACE_PHASE2 ) {
103 syslog( LOG_INFO, "rtmp_config ignoring data" );
108 * Check our seed information, and reconfigure.
110 if ( rh->rh_net != iface->i_addr.sat_addr.s_net ) {
111 if (( iface->i_flags & IFACE_SEED ) &&
112 rh->rh_net != iface->i_caddr.sat_addr.s_net) {
113 syslog( LOG_ERR, "rtmp_config net mismatch %u != %u",
115 ntohs( iface->i_addr.sat_addr.s_net ));
118 iface->i_addr.sat_addr.s_net = rh->rh_net;
121 * It is possible that we will corrupt our route database
122 * by just forcing this change. XXX
124 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = rh->rh_net;
126 setaddr( iface, IFACE_PHASE1, iface->i_addr.sat_addr.s_net,
127 iface->i_addr.sat_addr.s_node, rh->rh_net, rh->rh_net );
128 stabletimer = UNSTABLE;
131 /* add addr to loopback route */
132 if ((cc = looproute( iface, RTMP_ADD )) < 0 )
136 syslog( LOG_ERR, "rtmp_config: can't route %u.%u to loopback: %m",
137 ntohs( iface->i_addr.sat_addr.s_net ),
138 iface->i_addr.sat_addr.s_node );
141 syslog( LOG_INFO, "rtmp_config configured %s", iface->i_name );
142 iface->i_flags |= IFACE_CONFIG;
143 if ( iface == ciface ) {
144 ciface = ciface->i_next;
152 * Delete rtmp from the per-interface in-use table, remove all
153 * zone references, and remove the route from the kernel.
155 static void rtmp_delinuse( rtmp )
156 struct rtmptab *rtmp;
160 irt = rtmp->rt_gate->g_iface->i_rt;
161 if ( irt->rt_inext == rtmp ) { /* first */
162 if ( rtmp->rt_iprev == rtmp ) { /* only */
163 irt->rt_inext = NULL;
165 irt->rt_inext = rtmp->rt_inext;
166 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
169 if ( rtmp->rt_inext == NULL ) { /* last */
170 rtmp->rt_iprev->rt_inext = NULL;
171 irt->rt_inext->rt_iprev = rtmp->rt_iprev;
173 rtmp->rt_iprev->rt_inext = rtmp->rt_inext;
174 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
177 rtmp->rt_iprev = NULL;
178 rtmp->rt_inext = NULL;
180 /* remove zone map */
181 rtmp_delzonemap(rtmp);
183 /* remove old route */
184 gateroute( RTMP_DEL, rtmp );
188 * Add rtmp to the per-interface in-use table. No verification is done...
190 static void rtmp_addinuse( rtmp )
191 struct rtmptab *rtmp;
195 gateroute( RTMP_ADD, rtmp );
197 irt = rtmp->rt_gate->g_iface->i_rt;
198 if ( irt->rt_inext == NULL ) { /* empty list */
199 rtmp->rt_inext = NULL;
200 rtmp->rt_iprev = rtmp;
201 irt->rt_inext = rtmp;
203 rtmp->rt_inext = irt->rt_inext;
204 rtmp->rt_iprev = irt->rt_inext->rt_iprev;
205 irt->rt_inext->rt_iprev = rtmp;
206 irt->rt_inext = rtmp;
212 * Change the zone mapping to replace "from" with "to". This code assumes
213 * the consistency of both the route -> zone map and the zone -> route map.
214 * This is probably a bad idea. How can we insure that the data is good
215 * at this point? What do we do if we get several copies of a route in
218 static int rtmp_copyzones( to, from )
219 struct rtmptab *to, *from;
221 struct list *lz, *lr;
223 to->rt_zt = from->rt_zt;
225 if ( from->rt_flags & RTMPTAB_HASZONES ) {
226 to->rt_flags |= RTMPTAB_HASZONES;
228 for ( lz = to->rt_zt; lz; lz = lz->l_next ) {
229 for ( lr = ((struct ziptab *)lz->l_data)->zt_rt; lr; lr = lr->l_next ) {
230 if ( (struct rtmptab *)lr->l_data == from ) {
231 lr->l_data = (void *)to; /* cast BS */
236 syslog( LOG_ERR, "rtmp_copyzones z -> r without r -> z, abort" );
246 * Remove rtmp from the in-use table and the per-gate table.
247 * Free any associated space.
249 void rtmp_free( rtmp )
250 struct rtmptab *rtmp;
254 syslog(LOG_INFO, "rtmp_free: %u-%u", ntohs(rtmp->rt_firstnet),
255 ntohs(rtmp->rt_lastnet));
256 if ( rtmp->rt_iprev ) {
257 rtmp_delinuse( rtmp );
260 /* remove from per-gate */
261 gate = rtmp->rt_gate;
262 if ( gate->g_rt == rtmp ) { /* first */
263 if ( rtmp->rt_prev == rtmp ) { /* only */
266 gate->g_rt = rtmp->rt_next;
267 rtmp->rt_next->rt_prev = rtmp->rt_prev;
270 if ( rtmp->rt_next == NULL ) { /* last */
271 rtmp->rt_prev->rt_next = NULL;
272 gate->g_rt->rt_prev = rtmp->rt_prev;
274 rtmp->rt_prev->rt_next = rtmp->rt_next;
275 rtmp->rt_next->rt_prev = rtmp->rt_prev;
284 * Find a replacement for "replace". If we can't find a replacement,
285 * return 1. If we do find a replacement, return 0. -1 on error.
287 int rtmp_replace( replace )
288 struct rtmptab *replace;
290 struct interface *iface;
292 struct rtmptab *rtmp, *found = NULL;
294 syslog(LOG_INFO, "rtmp_replace %u-%u", ntohs(replace->rt_firstnet),
295 ntohs(replace->rt_lastnet));
296 for ( iface = interfaces; iface; iface = iface->i_next ) {
297 if ((replace->rt_iface != iface) &&
298 ((iface->i_flags & IFACE_ISROUTER) == 0))
301 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
302 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
303 if ( rtmp->rt_firstnet == replace->rt_firstnet &&
304 rtmp->rt_lastnet == replace->rt_lastnet ) {
305 if ( found == NULL || rtmp->rt_hops < found->rt_hops ) {
314 if ( found != replace ) {
315 if (rtmp_copyzones( found, replace ) < 0)
317 rtmp_delinuse( replace );
318 rtmp_addinuse( found );
319 if ( replace->rt_state == RTMPTAB_BAD ) {
320 rtmp_free( replace );
324 if ( replace->rt_hops == RTMPHOPS_POISON ) {
325 gateroute( RTMP_DEL, replace );
332 static int rtmp_new( rtmp )
333 struct rtmptab *rtmp;
337 extern int newrtmpdata;
342 * Do we already have a gateway for this route?
344 for ( i = interfaces; i; i = i->i_next ) {
345 if ((rtmp->rt_iface != i) &&
346 ((i->i_flags & IFACE_ISROUTER) == 0))
349 for ( r = i->i_rt; r; r = r->rt_inext ) {
350 /* Should check RTMPTAB_EXTENDED here. XXX */
351 if (( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_firstnet ) &&
352 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_firstnet )) ||
353 ( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_lastnet ) &&
354 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_lastnet ))) {
364 * This part of this routine is almost never run.
366 if ( i ) { /* can we get here without r being set? */
367 if ( r->rt_firstnet != rtmp->rt_firstnet ||
368 r->rt_lastnet != rtmp->rt_lastnet ) {
369 syslog( LOG_INFO, "rtmp_new netrange mismatch %u-%u != %u-%u",
370 ntohs( r->rt_firstnet ), ntohs( r->rt_lastnet ),
371 ntohs( rtmp->rt_firstnet ), ntohs( rtmp->rt_lastnet ));
376 * Note that our whole methodology is wrong, if we want to do
377 * route "load balancing." This entails changing our route
378 * each time we receive a tuple of equal value. In fact, we can't
379 * do this, using our method, since we only check against in-use
380 * routes when a tuple is new from a router.
382 if ( r->rt_hops < rtmp->rt_hops ) {
386 if (rtmp_copyzones( rtmp, r ) < 0)
391 rtmp_addinuse( rtmp );
396 int rtmp_packet( ap, from, data, len )
398 struct sockaddr_at *from;
403 struct rtmp_tuple rt, xrt;
405 struct interface *iface;
406 struct rtmptab *rtmp;
407 char *end, packet[ ATP_BUFSIZ ];
413 syslog( LOG_INFO, "rtmp_packet no data" );
417 iface = ap->ap_iface;
419 /* ignore our own packets */
420 if ( from->sat_addr.s_net == iface->i_addr.sat_addr.s_net &&
421 from->sat_addr.s_node == iface->i_addr.sat_addr.s_node ) {
426 case DDPTYPE_RTMPRD :
430 if ( data + sizeof( struct rtmprdhdr ) > end ) {
431 syslog( LOG_INFO, "rtmp_packet no data header" );
434 bcopy( data, &rh, sizeof( struct rtmprdhdr ));
435 data += sizeof( struct rtmprdhdr );
437 /* check rh address against from address */
438 if ( rh.rh_nodelen != 8 ) {
439 syslog( LOG_INFO, "rtmp_packet bad node len (%d)", rh.rh_nodelen );
442 if (( from->sat_addr.s_net != 0 &&
443 from->sat_addr.s_net != rh.rh_net ) ||
444 from->sat_addr.s_node != rh.rh_node ) {
445 syslog( LOG_INFO, "rtmp_packet address mismatch" );
449 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG )) == IFACE_ADDR ) {
450 if ( iface->i_flags & IFACE_NOROUTER ) {
451 /* remove addr to loopback route */
452 if ((cc = looproute( iface, RTMP_DEL )) < 0) {
453 syslog(LOG_ERR, "rtmp_packet: looproute");
458 syslog( LOG_ERR, "rtmp_packet: can't remove loopback: %m" );
460 iface->i_flags &= ~IFACE_NOROUTER;
462 syslog( LOG_INFO, "rtmp_packet router has become available" );
464 if ( iface->i_flags & IFACE_PHASE1 ) {
465 if (rtmp_config( &rh, iface ) < 0) {
466 syslog(LOG_ERR, "rtmp_packet: rtmp_config");
469 } else if (zip_getnetinfo( iface ) < 0) {
470 syslog(LOG_ERR, "rtmp_packet: zip_getnetinfo");
476 if (( iface->i_flags & IFACE_CONFIG ) == 0 ) {
481 * Parse first tuple. For phase 2, verify that net is correct.
483 if ( data + SZ_RTMPTUPLE > end ) {
484 syslog( LOG_INFO, "rtmp_packet missing first tuple" );
487 bcopy( data, &rt, SZ_RTMPTUPLE );
488 data += SZ_RTMPTUPLE;
490 if ( rt.rt_net == 0 ) {
491 if ( rt.rt_dist != 0x82 ) {
492 syslog( LOG_INFO, "rtmp_packet bad phase 1 version" );
497 * Grab the next tuple, since we don't want to pass the version
498 * number to the parsing code. We're assuming that there are
499 * no extended tuples in this packet.
501 if ( data + SZ_RTMPTUPLE > end ) {
502 syslog( LOG_INFO, "rtmp_packet missing second tuple" );
505 bcopy( data, &rt, SZ_RTMPTUPLE );
506 data += SZ_RTMPTUPLE;
507 } else if ( rt.rt_dist & 0x80 ) {
508 if ( data + SZ_RTMPTUPLE > end ) {
509 syslog( LOG_INFO, "rtmp_packet missing first range-end" );
512 bcopy( data, &xrt, SZ_RTMPTUPLE );
513 data += SZ_RTMPTUPLE;
515 if ( xrt.rt_dist != 0x82 ) {
516 syslog( LOG_INFO, "rtmp_packet bad phase 2 version" );
521 * Check for net range conflict.
523 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
524 xrt.rt_net != iface->i_rt->rt_lastnet ) {
525 syslog( LOG_INFO, "rtmp_packet interface mismatch" );
531 * Gatorboxes put a net number in the first tuple, even on
532 * phase 1 nets. This is wrong, but since we've got it, we
533 * might just as well check it.
534 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
535 rt.rt_net != iface->i_rt->rt_lastnet ) {
536 syslog( LOG_INFO, "rtmp_packet phase 1 interface mismatch" );
541 syslog( LOG_INFO, "rtmp_packet bad first tuple" );
549 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
550 if ( gate->g_sat.sat_addr.s_net == from->sat_addr.s_net &&
551 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
555 if ( !gate ) { /* new gateway */
556 if (( gate = (struct gate *)malloc( sizeof( struct gate ))) == 0 ) {
557 syslog( LOG_ERR, "rtmp_packet: malloc: %m" );
560 gate->g_next = iface->i_gate;
563 gate->g_iface = iface; /* need this? */
565 if ( iface->i_gate ) {
566 iface->i_gate->g_prev = gate;
568 iface->i_gate = gate;
569 syslog( LOG_INFO, "rtmp_packet gateway %u.%u up",
570 ntohs( gate->g_sat.sat_addr.s_net ),
571 gate->g_sat.sat_addr.s_node );
575 * Reset the timeout on this gateway. We'll remove the gateway
576 * entry, if the timeout gets to RTMPTAB_BAD.
578 gate->g_state = RTMPTAB_GOOD;
581 * Parse remaining tuples.
585 * Is route on this gateway?
587 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
588 if ( ntohs( rtmp->rt_firstnet ) <= ntohs( rt.rt_net ) &&
589 ntohs( rtmp->rt_lastnet ) >= ntohs( rt.rt_net )) {
592 if (( rt.rt_dist & 0x80 ) &&
593 ntohs( rtmp->rt_firstnet ) <= ntohs( xrt.rt_net ) &&
594 ntohs( rtmp->rt_lastnet ) >= ntohs( xrt.rt_net )) {
599 if ( rtmp ) { /* found it */
601 * Check for range conflicts. (This is getting a little
604 if ( rtmp->rt_firstnet != rt.rt_net ) {
605 syslog( LOG_INFO, "rtmp_packet firstnet mismatch %u!=%u",
606 ntohs( rtmp->rt_firstnet ), ntohs( rt.rt_net ));
609 if ( rt.rt_dist & 0x80 ) {
610 if (( rtmp->rt_flags & RTMPTAB_EXTENDED ) == 0 ) {
611 syslog( LOG_INFO, "rtmp_packet extended mismatch %u",
612 ntohs( rtmp->rt_firstnet ));
615 if ( rtmp->rt_lastnet != xrt.rt_net ) {
616 syslog( LOG_INFO, "rtmp_packet lastnet mismatch %u!=%u",
617 ntohs( rtmp->rt_lastnet ), ntohs( xrt.rt_net ));
621 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
622 syslog( LOG_INFO, "rtmp_packet !extended mismatch %u",
623 ntohs( rtmp->rt_firstnet ));
626 if ( rtmp->rt_lastnet != rt.rt_net ) {
627 syslog( LOG_INFO, "rtmp_packet lastnet mismatch %u!=%u",
628 ntohs( rtmp->rt_lastnet ), ntohs( rt.rt_net ));
633 rtmp->rt_state = RTMPTAB_GOOD;
636 * Check hop count. If the count has changed, update
637 * the routing database.
639 if (( rtmp->rt_hops != ( rt.rt_dist & 0x7f ) + 1 ) &&
640 ( rtmp->rt_hops != RTMPHOPS_POISON ||
641 ( rt.rt_dist & 0x7f ) + 1 <= RTMPHOPS_MAX )) {
642 if ( rtmp->rt_iprev ) { /* route is in use */
643 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
645 * If this was POISON, we've deleted it from
646 * the kernel. Add it back in.
648 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
649 gateroute( RTMP_ADD, rtmp );
651 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
654 * Hop count has gone up for this route.
655 * Search for a new best route. If we can't
656 * find one, just keep this route. "poison"
657 * route are deleted in as_timer().
659 if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
660 rtmp->rt_hops = RTMPHOPS_POISON;
662 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
664 if (rtmp_replace( rtmp ) < 0) {
665 syslog(LOG_ERR, "rtmp_packet: rtmp_replace");
669 } else { /* route not in use */
670 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
671 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
672 if (rtmp_new( rtmp ) < 0) {
673 syslog(LOG_ERR, "rtmp_packet: rtmp_new");
681 * Make the *next* node the head, since
682 * we're not likely to be asked for the same tuple twice
685 if ( rtmp->rt_next != 0 ) {
686 gate->g_rt->rt_prev->rt_next = gate->g_rt;
687 gate->g_rt = rtmp->rt_next;
690 } else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
691 syslog( LOG_INFO, "rtmp_packet bad hop count from %u.%u for %u",
692 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
694 } else { /* new for router */
695 if (( rtmp = newrt(iface)) == NULL ) {
696 syslog( LOG_ERR, "rtmp_packet: newrt: %m" );
699 rtmp->rt_firstnet = rt.rt_net;
700 if ( rt.rt_dist & 0x80 ) {
701 rtmp->rt_lastnet = xrt.rt_net;
702 rtmp->rt_flags = RTMPTAB_EXTENDED;
704 rtmp->rt_lastnet = rt.rt_net;
706 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
707 rtmp->rt_state = RTMPTAB_GOOD;
708 rtmp->rt_gate = gate;
711 * Add rtmptab entry to end of list (leave head alone).
713 if ( gate->g_rt == 0 ) {
714 rtmp->rt_prev = rtmp;
717 rtmp->rt_prev = gate->g_rt->rt_prev;
718 gate->g_rt->rt_prev->rt_next = rtmp;
719 gate->g_rt->rt_prev = rtmp;
722 if (rtmp_new( rtmp ) < 0) {
723 syslog(LOG_ERR, "rtmp_packet: rtmp_new");
728 if ( data + SZ_RTMPTUPLE > end ) {
731 bcopy( data, &rt, SZ_RTMPTUPLE );
732 data += SZ_RTMPTUPLE;
733 if ( rt.rt_dist & 0x80 ) {
734 if ( data + SZ_RTMPTUPLE > end ) {
735 syslog( LOG_INFO, "rtmp_packet missing range-end" );
738 bcopy( data, &xrt, SZ_RTMPTUPLE );
739 data += SZ_RTMPTUPLE;
744 * Make sure we've processed the whole packet.
747 syslog( LOG_INFO, "rtmp_packet length and count mismatch" );
755 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
756 iface->i_rt->rt_zt == 0 ||
757 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
762 *data++ = DDPTYPE_RTMPRD;
763 rh.rh_net = iface->i_addr.sat_addr.s_net;
765 rh.rh_node = iface->i_addr.sat_addr.s_node;
766 bcopy( &rh, data, sizeof( struct rtmp_head ));
767 data += sizeof( struct rtmp_head );
769 if ( iface->i_flags & IFACE_PHASE2 ) {
770 rt.rt_net = iface->i_rt->rt_firstnet;
772 bcopy( &rt, data, SZ_RTMPTUPLE );
773 data += SZ_RTMPTUPLE;
775 rt.rt_net = iface->i_rt->rt_lastnet;
777 bcopy( &rt, data, SZ_RTMPTUPLE );
778 data += SZ_RTMPTUPLE;
780 if ( sendto( ap->ap_fd, packet, data - packet, 0,
781 (struct sockaddr *)from,
782 sizeof( struct sockaddr_at )) < 0 ) {
783 syslog( LOG_ERR, "as_timer sendto: %m" );
785 } else if ( *data == 2 || *data == 3 ) {
787 printf( "rtmp_packet rdr (%d) from %u.%u\n",
788 *data, ntohs( from->sat_addr.s_net ),
789 from->sat_addr.s_node );
792 syslog( LOG_INFO, "rtmp_packet unknown request from %u.%u\n",
793 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
798 syslog( LOG_INFO, "rtmp_packet bad ddp type from %u.%u",
799 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
806 int rtmp_request( iface )
807 struct interface *iface;
809 struct sockaddr_at sat;
811 char *data, packet[ 2 ];
813 syslog( LOG_INFO, "rtmp_request for %s", iface->i_name );
815 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
816 if ( ap->ap_packet == rtmp_packet ) {
821 syslog( LOG_ERR, "rtmp_request can't find rtmp socket!" );
826 *data++ = DDPTYPE_RTMPR;
827 *data++ = RTMPROP_REQUEST;
830 * There is a problem with the net zero "hint" hack.
832 bzero( &sat, sizeof( struct sockaddr_at ));
834 sat.sat_len = sizeof( struct sockaddr_at );
836 sat.sat_family = AF_APPLETALK;
837 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
838 sat.sat_addr.s_node = ATADDR_BCAST;
839 sat.sat_port = ap->ap_port;
840 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
841 sizeof( struct sockaddr_at )) < 0 ) {
842 syslog( LOG_ERR, "rtmp_request sendto: %m" );
849 int looproute( iface, cmd )
850 struct interface *iface;
853 struct sockaddr_at dst, loop;
855 if ( cmd == RTMP_DEL && ( iface->i_flags & IFACE_LOOP ) == 0 ) {
856 syslog( LOG_ERR, "looproute panic no route" );
860 if ( cmd == RTMP_ADD && ( iface->i_flags & IFACE_LOOP )) {
861 syslog( LOG_ERR, "looproute panic two routes" );
865 bzero( &dst, sizeof( struct sockaddr_at ));
867 dst.sat_len = sizeof( struct sockaddr_at );
869 dst.sat_family = AF_APPLETALK;
870 dst.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
871 dst.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
872 bzero( &loop, sizeof( struct sockaddr_at ));
874 loop.sat_len = sizeof( struct sockaddr_at );
876 loop.sat_family = AF_APPLETALK;
877 loop.sat_addr.s_net = htons( ATADDR_ANYNET );
878 loop.sat_addr.s_node = ATADDR_ANYNODE;
880 if ( route( cmd, &dst, &loop, RTF_UP | RTF_HOST )) {
883 if ( cmd == RTMP_ADD ) {
884 iface->i_flags |= IFACE_LOOP;
886 if ( cmd == RTMP_DEL ) {
887 iface->i_flags &= ~IFACE_LOOP;
892 int gateroute( command, rtmp )
894 struct rtmptab *rtmp;
896 struct sockaddr_at dst, gate;
899 if ( command == RTMP_DEL && ( rtmp->rt_flags & RTMPTAB_ROUTE ) == 0 ) {
902 if ( command == RTMP_ADD && ( rtmp->rt_flags & RTMPTAB_ROUTE )) {
906 net = ntohs( rtmp->rt_firstnet );
908 * Since we will accept routes from gateways who advertise their
909 * address as 0.YY, we must munge the gateway address we give to
910 * the kernel. Otherwise, we'll get a bunch of routes to the loop
911 * back interface, and who wants that?
913 bzero( &gate, sizeof( struct sockaddr_at ));
915 gate.sat_len = sizeof( struct sockaddr_at );
917 gate.sat_family = AF_APPLETALK;
918 gate.sat_addr.s_net = rtmp->rt_gate->g_sat.sat_addr.s_net;
919 gate.sat_addr.s_node = rtmp->rt_gate->g_sat.sat_addr.s_node;
920 if ( gate.sat_addr.s_net == 0 ) {
921 gate.sat_addr.s_net = net;
924 bzero( &dst, sizeof( struct sockaddr_at ));
926 dst.sat_len = sizeof( struct sockaddr_at );
928 dst.sat_family = AF_APPLETALK;
929 dst.sat_addr.s_node = ATADDR_ANYNODE;
932 dst.sat_addr.s_net = htons( net );
933 if ( route( command, &dst, &gate, RTF_UP | RTF_GATEWAY )) {
934 syslog( LOG_ERR, "route: %u -> %u.%u: %m", net,
935 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
938 } while ( net++ < ntohs( rtmp->rt_lastnet ));
940 if ( command == RTMP_ADD ) {
941 rtmp->rt_flags |= RTMPTAB_ROUTE;
943 if ( command == RTMP_DEL ) {
944 rtmp->rt_flags &= ~RTMPTAB_ROUTE;
951 newrt(const struct interface *iface)
953 struct rtmptab *rtmp;
955 if (( rtmp = (struct rtmptab *)calloc(1, sizeof(struct rtmptab))) == 0 ) {
959 rtmp->rt_iface = iface;