2 * $Id: rtmp.c,v 1.12.8.1 2004-05-12 21:21:48 didg Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
15 #include <atalk/logger.h>
16 #include <sys/types.h>
17 #include <sys/param.h>
18 #include <sys/socket.h>
19 #include <sys/ioctl.h>
22 #include <net/route.h>
25 #include <net/route.h>
26 #include <netatalk/endian.h>
27 #include <netatalk/at.h>
30 #include <sys/sockio.h>
33 #include <atalk/ddp.h>
34 #include <atalk/atp.h>
35 #include <atalk/rtmp.h>
37 #include "interface.h"
46 void rtmp_delzonemap(rtmp)
49 struct list *lz, *flz, *lr, *flr;
53 while ( lz ) { /* for each zone */
54 zt = (struct ziptab *)lz->l_data;
56 while ( lr ) { /* for each route */
57 if ( (struct rtmptab *)lr->l_data == rtmp ) {
58 if ( lr->l_prev == NULL ) { /* head */
59 if ( lr->l_next == NULL ) { /* last route in zone */
60 if ( zt->zt_prev == NULL ) {
63 zt->zt_prev->zt_next = zt->zt_next;
65 if ( zt->zt_next == NULL ) {
66 ziplast = zt->zt_prev;
68 zt->zt_next->zt_prev = zt->zt_prev;
74 zt->zt_rt = lr->l_next;
77 lr->l_prev->l_next = lr->l_next;
79 if ( lr->l_next != NULL ) {
80 lr->l_next->l_prev = lr->l_prev;
98 * Complete configuration for phase 1 interface using RTMP information.
100 static int rtmp_config( rh, iface )
101 struct rtmp_head *rh;
102 struct interface *iface;
104 extern int stabletimer;
108 * If we're configuring a phase 2 interface, don't complete
109 * configuration with RTMP.
111 if ( iface->i_flags & IFACE_PHASE2 ) {
112 LOG(log_info, logtype_atalkd, "rtmp_config ignoring data" );
117 * Check our seed information, and reconfigure.
119 if ( rh->rh_net != iface->i_addr.sat_addr.s_net ) {
120 if (( iface->i_flags & IFACE_SEED ) &&
121 rh->rh_net != iface->i_caddr.sat_addr.s_net) {
122 LOG(log_error, logtype_atalkd, "rtmp_config net mismatch %u != %u",
124 ntohs( iface->i_addr.sat_addr.s_net ));
127 iface->i_addr.sat_addr.s_net = rh->rh_net;
130 * It is possible that we will corrupt our route database
131 * by just forcing this change. XXX
133 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = rh->rh_net;
135 setaddr( iface, IFACE_PHASE1, iface->i_addr.sat_addr.s_net,
136 iface->i_addr.sat_addr.s_node, rh->rh_net, rh->rh_net );
137 stabletimer = UNSTABLE;
140 /* add addr to loopback route */
141 if ((cc = looproute( iface, RTMP_ADD )) < 0 )
145 LOG(log_error, logtype_atalkd, "rtmp_config: can't route %u.%u to loopback: %s",
146 ntohs( iface->i_addr.sat_addr.s_net ),
147 iface->i_addr.sat_addr.s_node,
151 LOG(log_info, logtype_atalkd, "rtmp_config configured %s", iface->i_name );
152 iface->i_flags |= IFACE_CONFIG;
153 if ( iface == ciface ) {
154 ciface = ciface->i_next;
162 * Delete rtmp from the per-interface in-use table, remove all
163 * zone references, and remove the route from the kernel.
165 static void rtmp_delinuse( rtmp )
166 struct rtmptab *rtmp;
170 irt = rtmp->rt_gate->g_iface->i_rt;
171 if ( irt->rt_inext == rtmp ) { /* first */
172 if ( rtmp->rt_iprev == rtmp ) { /* only */
173 irt->rt_inext = NULL;
175 irt->rt_inext = rtmp->rt_inext;
176 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
179 if ( rtmp->rt_inext == NULL ) { /* last */
180 rtmp->rt_iprev->rt_inext = NULL;
181 irt->rt_inext->rt_iprev = rtmp->rt_iprev;
183 rtmp->rt_iprev->rt_inext = rtmp->rt_inext;
184 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
187 rtmp->rt_iprev = NULL;
188 rtmp->rt_inext = NULL;
190 /* remove zone map */
191 rtmp_delzonemap(rtmp);
193 /* remove old route */
194 gateroute( RTMP_DEL, rtmp );
198 * Add rtmp to the per-interface in-use table. No verification is done...
200 static void rtmp_addinuse( rtmp )
201 struct rtmptab *rtmp;
205 gateroute( RTMP_ADD, rtmp );
207 irt = rtmp->rt_gate->g_iface->i_rt;
208 if ( irt->rt_inext == NULL ) { /* empty list */
209 rtmp->rt_inext = NULL;
210 rtmp->rt_iprev = rtmp;
211 irt->rt_inext = rtmp;
213 rtmp->rt_inext = irt->rt_inext;
214 rtmp->rt_iprev = irt->rt_inext->rt_iprev;
215 irt->rt_inext->rt_iprev = rtmp;
216 irt->rt_inext = rtmp;
222 * Change the zone mapping to replace "from" with "to". This code assumes
223 * the consistency of both the route -> zone map and the zone -> route map.
224 * This is probably a bad idea. How can we insure that the data is good
225 * at this point? What do we do if we get several copies of a route in
228 static int rtmp_copyzones( to, from )
229 struct rtmptab *to, *from;
231 struct list *lz, *lr;
233 to->rt_zt = from->rt_zt;
235 if ( from->rt_flags & RTMPTAB_HASZONES ) {
236 to->rt_flags |= RTMPTAB_HASZONES;
238 for ( lz = to->rt_zt; lz; lz = lz->l_next ) {
239 for ( lr = ((struct ziptab *)lz->l_data)->zt_rt; lr; lr = lr->l_next ) {
240 if ( (struct rtmptab *)lr->l_data == from ) {
241 lr->l_data = (void *)to; /* cast BS */
246 LOG(log_error, logtype_atalkd, "rtmp_copyzones z -> r without r -> z, abort" );
256 * Remove rtmp from the in-use table and the per-gate table.
257 * Free any associated space.
259 void rtmp_free( rtmp )
260 struct rtmptab *rtmp;
264 LOG(log_info, logtype_atalkd, "rtmp_free: %u-%u", ntohs(rtmp->rt_firstnet),
265 ntohs(rtmp->rt_lastnet));
266 if ( rtmp->rt_iprev ) {
267 rtmp_delinuse( rtmp );
270 /* remove from per-gate */
271 gate = rtmp->rt_gate;
272 if ( gate->g_rt == rtmp ) { /* first */
273 if ( rtmp->rt_prev == rtmp ) { /* only */
276 gate->g_rt = rtmp->rt_next;
277 rtmp->rt_next->rt_prev = rtmp->rt_prev;
280 if ( rtmp->rt_next == NULL ) { /* last */
281 rtmp->rt_prev->rt_next = NULL;
282 gate->g_rt->rt_prev = rtmp->rt_prev;
284 rtmp->rt_prev->rt_next = rtmp->rt_next;
285 rtmp->rt_next->rt_prev = rtmp->rt_prev;
294 * Find a replacement for "replace". If we can't find a replacement,
295 * return 1. If we do find a replacement, return 0. -1 on error.
297 int rtmp_replace( replace )
298 struct rtmptab *replace;
300 struct interface *iface;
302 struct rtmptab *rtmp, *found = NULL;
304 LOG(log_info, logtype_atalkd, "rtmp_replace %u-%u", ntohs(replace->rt_firstnet),
305 ntohs(replace->rt_lastnet));
306 for ( iface = interfaces; iface; iface = iface->i_next ) {
307 if ((replace->rt_iface != iface) &&
308 ((iface->i_flags & IFACE_ISROUTER) == 0))
311 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
312 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
313 if ( rtmp->rt_firstnet == replace->rt_firstnet &&
314 rtmp->rt_lastnet == replace->rt_lastnet ) {
315 if ( found == NULL || rtmp->rt_hops < found->rt_hops ) {
324 if ( found != replace ) {
325 if (rtmp_copyzones( found, replace ) < 0)
327 rtmp_delinuse( replace );
328 rtmp_addinuse( found );
329 if ( replace->rt_state == RTMPTAB_BAD ) {
330 rtmp_free( replace );
334 if ( replace->rt_hops == RTMPHOPS_POISON ) {
335 gateroute( RTMP_DEL, replace );
342 static int rtmp_new( rtmp )
343 struct rtmptab *rtmp;
347 extern int newrtmpdata;
352 * Do we already have a gateway for this route?
354 for ( i = interfaces; i; i = i->i_next ) {
355 if ((rtmp->rt_iface != i) &&
356 ((i->i_flags & IFACE_ISROUTER) == 0))
359 for ( r = i->i_rt; r; r = r->rt_inext ) {
360 /* Should check RTMPTAB_EXTENDED here. XXX */
361 if (( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_firstnet ) &&
362 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_firstnet )) ||
363 ( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_lastnet ) &&
364 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_lastnet ))) {
374 * This part of this routine is almost never run.
376 if ( i ) { /* can we get here without r being set? */
377 if ( r->rt_firstnet != rtmp->rt_firstnet ||
378 r->rt_lastnet != rtmp->rt_lastnet ) {
379 LOG(log_info, logtype_atalkd, "rtmp_new netrange mismatch %u-%u != %u-%u",
380 ntohs( r->rt_firstnet ), ntohs( r->rt_lastnet ),
381 ntohs( rtmp->rt_firstnet ), ntohs( rtmp->rt_lastnet ));
386 * Note that our whole methodology is wrong, if we want to do
387 * route "load balancing." This entails changing our route
388 * each time we receive a tuple of equal value. In fact, we can't
389 * do this, using our method, since we only check against in-use
390 * routes when a tuple is new from a router.
392 if ( r->rt_hops < rtmp->rt_hops ) {
396 if (rtmp_copyzones( rtmp, r ) < 0)
401 rtmp_addinuse( rtmp );
406 int rtmp_packet( ap, from, data, len )
408 struct sockaddr_at *from;
413 struct rtmp_tuple rt, xrt;
415 struct interface *iface;
416 struct rtmptab *rtmp;
417 char *end, packet[ ATP_BUFSIZ ];
423 LOG(log_info, logtype_atalkd, "rtmp_packet no data" );
427 iface = ap->ap_iface;
429 /* ignore our own packets */
430 if ( from->sat_addr.s_net == iface->i_addr.sat_addr.s_net &&
431 from->sat_addr.s_node == iface->i_addr.sat_addr.s_node ) {
436 case DDPTYPE_RTMPRD :
440 if ( data + sizeof( struct rtmprdhdr ) > end ) {
441 LOG(log_info, logtype_atalkd, "rtmp_packet no data header" );
444 memcpy( &rh, data, sizeof( struct rtmprdhdr ));
445 data += sizeof( struct rtmprdhdr );
447 /* check rh address against from address */
448 if ( rh.rh_nodelen != 8 ) {
449 LOG(log_info, logtype_atalkd, "rtmp_packet bad node len (%d)", rh.rh_nodelen );
452 if (( from->sat_addr.s_net != 0 &&
453 from->sat_addr.s_net != rh.rh_net ) ||
454 from->sat_addr.s_node != rh.rh_node ) {
455 LOG(log_info, logtype_atalkd, "rtmp_packet address mismatch" );
459 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG )) == IFACE_ADDR ) {
460 if ( iface->i_flags & IFACE_NOROUTER ) {
461 /* remove addr to loopback route */
462 if ((cc = looproute( iface, RTMP_DEL )) < 0) {
463 LOG(log_error, logtype_atalkd, "rtmp_packet: looproute");
468 LOG(log_error, logtype_atalkd, "rtmp_packet: can't remove loopback: %s",
471 iface->i_flags &= ~IFACE_NOROUTER;
473 LOG(log_info, logtype_atalkd, "rtmp_packet router has become available" );
475 if ( iface->i_flags & IFACE_PHASE1 ) {
476 if (rtmp_config( &rh, iface ) < 0) {
477 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_config");
480 } else if (zip_getnetinfo( iface ) < 0) {
481 LOG(log_error, logtype_atalkd, "rtmp_packet: zip_getnetinfo");
487 if (( iface->i_flags & IFACE_CONFIG ) == 0 ) {
492 * Parse first tuple. For phase 2, verify that net is correct.
494 if ( data + SZ_RTMPTUPLE > end ) {
495 LOG(log_info, logtype_atalkd, "rtmp_packet missing first tuple" );
498 memcpy( &rt, data, SZ_RTMPTUPLE );
499 data += SZ_RTMPTUPLE;
501 if ( rt.rt_net == 0 ) {
502 if ( rt.rt_dist != 0x82 ) {
503 LOG(log_info, logtype_atalkd, "rtmp_packet bad phase 1 version" );
508 * Grab the next tuple, since we don't want to pass the version
509 * number to the parsing code. We're assuming that there are
510 * no extended tuples in this packet.
512 if ( data + SZ_RTMPTUPLE > end ) {
513 LOG(log_info, logtype_atalkd, "rtmp_packet missing second tuple" );
516 memcpy( &rt, data, SZ_RTMPTUPLE );
517 data += SZ_RTMPTUPLE;
518 } else if ( rt.rt_dist & 0x80 ) {
519 if ( data + SZ_RTMPTUPLE > end ) {
520 LOG(log_info, logtype_atalkd, "rtmp_packet missing first range-end" );
523 memcpy( &xrt, data, SZ_RTMPTUPLE );
524 data += SZ_RTMPTUPLE;
526 if ( xrt.rt_dist != 0x82 ) {
527 LOG(log_info, logtype_atalkd, "rtmp_packet bad phase 2 version" );
532 * Check for net range conflict.
534 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
535 xrt.rt_net != iface->i_rt->rt_lastnet ) {
536 LOG(log_info, logtype_atalkd, "rtmp_packet interface mismatch" );
542 * Gatorboxes put a net number in the first tuple, even on
543 * phase 1 nets. This is wrong, but since we've got it, we
544 * might just as well check it.
545 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
546 rt.rt_net != iface->i_rt->rt_lastnet ) {
547 LOG(log_info, logtype_atalkd, "rtmp_packet phase 1 interface mismatch" );
551 #else /* PHASE1NET */
552 LOG(log_info, logtype_atalkd, "rtmp_packet bad first tuple" );
554 #endif /* PHASE1NET */
560 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
561 if ( gate->g_sat.sat_addr.s_net == from->sat_addr.s_net &&
562 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
566 if ( !gate ) { /* new gateway */
567 if (( gate = (struct gate *)malloc( sizeof( struct gate ))) == 0 ) {
568 LOG(log_error, logtype_atalkd, "rtmp_packet: malloc: %s", strerror(errno) );
571 gate->g_next = iface->i_gate;
574 gate->g_iface = iface; /* need this? */
576 if ( iface->i_gate ) {
577 iface->i_gate->g_prev = gate;
579 iface->i_gate = gate;
580 LOG(log_info, logtype_atalkd, "rtmp_packet gateway %u.%u up",
581 ntohs( gate->g_sat.sat_addr.s_net ),
582 gate->g_sat.sat_addr.s_node );
586 * Reset the timeout on this gateway. We'll remove the gateway
587 * entry, if the timeout gets to RTMPTAB_BAD.
589 gate->g_state = RTMPTAB_GOOD;
592 * Parse remaining tuples.
596 * Is route on this gateway?
598 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
599 if ( ntohs( rtmp->rt_firstnet ) <= ntohs( rt.rt_net ) &&
600 ntohs( rtmp->rt_lastnet ) >= ntohs( rt.rt_net )) {
603 if (( rt.rt_dist & 0x80 ) &&
604 ntohs( rtmp->rt_firstnet ) <= ntohs( xrt.rt_net ) &&
605 ntohs( rtmp->rt_lastnet ) >= ntohs( xrt.rt_net )) {
610 if ( rtmp ) { /* found it */
612 * Check for range conflicts. (This is getting a little
615 if ( rtmp->rt_firstnet != rt.rt_net ) {
616 LOG(log_info, logtype_atalkd, "rtmp_packet firstnet mismatch %u!=%u",
617 ntohs( rtmp->rt_firstnet ), ntohs( rt.rt_net ));
620 if ( rt.rt_dist & 0x80 ) {
621 if (( rtmp->rt_flags & RTMPTAB_EXTENDED ) == 0 ) {
622 LOG(log_info, logtype_atalkd, "rtmp_packet extended mismatch %u",
623 ntohs( rtmp->rt_firstnet ));
626 if ( rtmp->rt_lastnet != xrt.rt_net ) {
627 LOG(log_info, logtype_atalkd, "rtmp_packet lastnet mismatch %u!=%u",
628 ntohs( rtmp->rt_lastnet ), ntohs( xrt.rt_net ));
632 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
633 LOG(log_info, logtype_atalkd, "rtmp_packet !extended mismatch %u",
634 ntohs( rtmp->rt_firstnet ));
637 if ( rtmp->rt_lastnet != rt.rt_net ) {
638 LOG(log_info, logtype_atalkd, "rtmp_packet lastnet mismatch %u!=%u",
639 ntohs( rtmp->rt_lastnet ), ntohs( rt.rt_net ));
644 rtmp->rt_state = RTMPTAB_GOOD;
647 * Check hop count. If the count has changed, update
648 * the routing database.
650 if (( rtmp->rt_hops != ( rt.rt_dist & 0x7f ) + 1 ) &&
651 ( rtmp->rt_hops != RTMPHOPS_POISON ||
652 ( rt.rt_dist & 0x7f ) + 1 <= RTMPHOPS_MAX )) {
653 if ( rtmp->rt_iprev ) { /* route is in use */
654 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
656 * If this was POISON, we've deleted it from
657 * the kernel. Add it back in.
659 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
660 gateroute( RTMP_ADD, rtmp );
662 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
665 * Hop count has gone up for this route.
666 * Search for a new best route. If we can't
667 * find one, just keep this route. "poison"
668 * route are deleted in as_timer().
670 if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
671 rtmp->rt_hops = RTMPHOPS_POISON;
673 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
675 if (rtmp_replace( rtmp ) < 0) {
676 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_replace");
680 } else { /* route not in use */
681 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
682 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
683 if (rtmp_new( rtmp ) < 0) {
684 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_new");
692 * Make the *next* node the head, since
693 * we're not likely to be asked for the same tuple twice
696 if ( rtmp->rt_next != 0 ) {
697 gate->g_rt->rt_prev->rt_next = gate->g_rt;
698 gate->g_rt = rtmp->rt_next;
701 } else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
702 LOG(log_info, logtype_atalkd, "rtmp_packet bad hop count from %u.%u for %u",
703 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
705 } else { /* new for router */
706 if (( rtmp = newrt(iface)) == NULL ) {
707 LOG(log_error, logtype_atalkd, "rtmp_packet: newrt: %s", strerror(errno) );
710 rtmp->rt_firstnet = rt.rt_net;
711 if ( rt.rt_dist & 0x80 ) {
712 rtmp->rt_lastnet = xrt.rt_net;
713 rtmp->rt_flags = RTMPTAB_EXTENDED;
715 rtmp->rt_lastnet = rt.rt_net;
717 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
718 rtmp->rt_state = RTMPTAB_GOOD;
719 rtmp->rt_gate = gate;
722 * Add rtmptab entry to end of list (leave head alone).
724 if ( gate->g_rt == 0 ) {
725 rtmp->rt_prev = rtmp;
728 rtmp->rt_prev = gate->g_rt->rt_prev;
729 gate->g_rt->rt_prev->rt_next = rtmp;
730 gate->g_rt->rt_prev = rtmp;
733 if (rtmp_new( rtmp ) < 0) {
734 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_new");
739 if ( data + SZ_RTMPTUPLE > end ) {
742 memcpy( &rt, data, SZ_RTMPTUPLE );
743 data += SZ_RTMPTUPLE;
744 if ( rt.rt_dist & 0x80 ) {
745 if ( data + SZ_RTMPTUPLE > end ) {
746 LOG(log_info, logtype_atalkd, "rtmp_packet missing range-end" );
749 memcpy( &xrt, data, SZ_RTMPTUPLE );
750 data += SZ_RTMPTUPLE;
755 * Make sure we've processed the whole packet.
758 LOG(log_info, logtype_atalkd, "rtmp_packet length and count mismatch" );
766 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
767 iface->i_rt->rt_zt == 0 ||
768 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
773 *data++ = DDPTYPE_RTMPRD;
774 rh.rh_net = iface->i_addr.sat_addr.s_net;
776 rh.rh_node = iface->i_addr.sat_addr.s_node;
777 memcpy( data, &rh, sizeof( struct rtmp_head ));
778 data += sizeof( struct rtmp_head );
780 if ( iface->i_flags & IFACE_PHASE2 ) {
781 rt.rt_net = iface->i_rt->rt_firstnet;
783 memcpy( data, &rt, SZ_RTMPTUPLE );
784 data += SZ_RTMPTUPLE;
786 rt.rt_net = iface->i_rt->rt_lastnet;
788 memcpy( data, &rt, SZ_RTMPTUPLE );
789 data += SZ_RTMPTUPLE;
791 if ( sendto( ap->ap_fd, packet, data - packet, 0,
792 (struct sockaddr *)from,
793 sizeof( struct sockaddr_at )) < 0 ) {
794 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
796 } else if ( *data == 2 || *data == 3 ) {
798 printf( "rtmp_packet rdr (%d) from %u.%u\n",
799 *data, ntohs( from->sat_addr.s_net ),
800 from->sat_addr.s_node );
803 LOG(log_info, logtype_atalkd, "rtmp_packet unknown request from %u.%u",
804 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
809 LOG(log_info, logtype_atalkd, "rtmp_packet bad ddp type from %u.%u",
810 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
817 int rtmp_request( iface )
818 struct interface *iface;
820 struct sockaddr_at sat;
822 char *data, packet[ 2 ];
824 LOG(log_info, logtype_atalkd, "rtmp_request for %s", iface->i_name );
826 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
827 if ( ap->ap_packet == rtmp_packet ) {
832 LOG(log_error, logtype_atalkd, "rtmp_request can't find rtmp socket!" );
837 *data++ = DDPTYPE_RTMPR;
838 *data++ = RTMPROP_REQUEST;
841 * There is a problem with the net zero "hint" hack.
843 memset( &sat, 0, sizeof( struct sockaddr_at ));
845 sat.sat_len = sizeof( struct sockaddr_at );
847 sat.sat_family = AF_APPLETALK;
848 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
849 sat.sat_addr.s_node = ATADDR_BCAST;
850 sat.sat_port = ap->ap_port;
851 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
852 sizeof( struct sockaddr_at )) < 0 ) {
853 LOG(log_error, logtype_atalkd, "rtmp_request sendto: %s", strerror(errno) );
860 int looproute( iface, cmd )
861 struct interface *iface;
864 struct sockaddr_at dst, loop;
866 if ( cmd == RTMP_DEL && ( iface->i_flags & IFACE_LOOP ) == 0 ) {
867 LOG(log_error, logtype_atalkd, "looproute panic no route" );
871 if ( cmd == RTMP_ADD && ( iface->i_flags & IFACE_LOOP )) {
872 LOG(log_error, logtype_atalkd, "looproute panic two routes" );
876 memset( &dst, 0, sizeof( struct sockaddr_at ));
878 dst.sat_len = sizeof( struct sockaddr_at );
880 dst.sat_family = AF_APPLETALK;
881 dst.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
882 dst.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
883 memset( &loop, 0, sizeof( struct sockaddr_at ));
885 loop.sat_len = sizeof( struct sockaddr_at );
887 loop.sat_family = AF_APPLETALK;
888 loop.sat_addr.s_net = htons( ATADDR_ANYNET );
889 loop.sat_addr.s_node = ATADDR_ANYNODE;
893 (struct sockaddr *) &dst,
894 (struct sockaddr *) &loop,
895 RTF_UP | RTF_HOST ) ) {
900 (struct sockaddr_at *) &dst,
901 (struct sockaddr_at *) &loop,
902 RTF_UP | RTF_HOST ) ) {
906 if ( cmd == RTMP_ADD ) {
907 iface->i_flags |= IFACE_LOOP;
909 if ( cmd == RTMP_DEL ) {
910 iface->i_flags &= ~IFACE_LOOP;
915 int gateroute( command, rtmp )
916 unsigned int command;
917 struct rtmptab *rtmp;
919 struct sockaddr_at dst, gate;
922 if ( command == RTMP_DEL && ( rtmp->rt_flags & RTMPTAB_ROUTE ) == 0 ) {
925 if ( command == RTMP_ADD && ( rtmp->rt_flags & RTMPTAB_ROUTE )) {
929 net = ntohs( rtmp->rt_firstnet );
931 * Since we will accept routes from gateways who advertise their
932 * address as 0.YY, we must munge the gateway address we give to
933 * the kernel. Otherwise, we'll get a bunch of routes to the loop
934 * back interface, and who wants that?
936 memset( &gate, 0, sizeof( struct sockaddr_at ));
938 gate.sat_len = sizeof( struct sockaddr_at );
940 gate.sat_family = AF_APPLETALK;
941 gate.sat_addr.s_net = rtmp->rt_gate->g_sat.sat_addr.s_net;
942 gate.sat_addr.s_node = rtmp->rt_gate->g_sat.sat_addr.s_node;
943 if ( gate.sat_addr.s_net == 0 ) {
944 gate.sat_addr.s_net = net;
947 memset( &dst, 0, sizeof( struct sockaddr_at ));
949 dst.sat_len = sizeof( struct sockaddr_at );
951 dst.sat_family = AF_APPLETALK;
952 dst.sat_addr.s_node = ATADDR_ANYNODE;
955 dst.sat_addr.s_net = htons( net );
958 (struct sockaddr *) &dst,
959 (struct sockaddr *) &gate,
960 RTF_UP | RTF_GATEWAY )) {
961 LOG(log_error, logtype_atalkd, "route: %u -> %u.%u: %s", net,
962 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node,
968 (struct sockaddr_at *) &dst,
969 (struct sockaddr_at *) &gate,
970 RTF_UP | RTF_GATEWAY )) {
971 LOG(log_error, logtype_atalkd, "route: %u -> %u.%u: %m", net,
972 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
975 #endif /* ! BSD4_4 */
976 } while ( net++ < ntohs( rtmp->rt_lastnet ));
978 if ( command == RTMP_ADD ) {
979 rtmp->rt_flags |= RTMPTAB_ROUTE;
981 if ( command == RTMP_DEL ) {
982 rtmp->rt_flags &= ~RTMPTAB_ROUTE;
989 newrt(const struct interface *iface)
991 struct rtmptab *rtmp;
993 if (( rtmp = (struct rtmptab *)calloc(1, sizeof(struct rtmptab))) == 0 ) {
997 rtmp->rt_iface = iface;