2 * $Id: rtmp.c,v 1.16 2009-10-14 02:24:05 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(struct rtmptab *rtmp)
48 struct list *lz, *flz, *lr, *flr;
52 while ( lz ) { /* for each zone */
53 zt = (struct ziptab *)lz->l_data;
55 while ( lr ) { /* for each route */
56 if ( (struct rtmptab *)lr->l_data == rtmp ) {
57 if ( lr->l_prev == NULL ) { /* head */
58 if ( lr->l_next == NULL ) { /* last route in zone */
59 if ( zt->zt_prev == NULL ) {
62 zt->zt_prev->zt_next = zt->zt_next;
64 if ( zt->zt_next == NULL ) {
65 ziplast = zt->zt_prev;
67 zt->zt_next->zt_prev = zt->zt_prev;
73 zt->zt_rt = lr->l_next;
76 lr->l_prev->l_next = lr->l_next;
78 if ( lr->l_next != NULL ) {
79 lr->l_next->l_prev = lr->l_prev;
97 * Complete configuration for phase 1 interface using RTMP information.
99 static int rtmp_config( struct rtmp_head *rh, struct interface *iface)
101 extern int stabletimer;
105 * If we're configuring a phase 2 interface, don't complete
106 * configuration with RTMP.
108 if ( iface->i_flags & IFACE_PHASE2 ) {
109 LOG(log_info, logtype_atalkd, "rtmp_config ignoring data" );
114 * Check our seed information, and reconfigure.
116 if ( rh->rh_net != iface->i_addr.sat_addr.s_net ) {
117 if (( iface->i_flags & IFACE_SEED ) &&
118 rh->rh_net != iface->i_caddr.sat_addr.s_net) {
119 LOG(log_error, logtype_atalkd, "rtmp_config net mismatch %u != %u",
121 ntohs( iface->i_addr.sat_addr.s_net ));
124 iface->i_addr.sat_addr.s_net = rh->rh_net;
127 * It is possible that we will corrupt our route database
128 * by just forcing this change. XXX
130 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = rh->rh_net;
132 setaddr( iface, IFACE_PHASE1, iface->i_addr.sat_addr.s_net,
133 iface->i_addr.sat_addr.s_node, rh->rh_net, rh->rh_net );
134 stabletimer = UNSTABLE;
137 /* add addr to loopback route */
138 if ((cc = looproute( iface, RTMP_ADD )) < 0 )
142 LOG(log_error, logtype_atalkd, "rtmp_config: can't route %u.%u to loopback: %s",
143 ntohs( iface->i_addr.sat_addr.s_net ),
144 iface->i_addr.sat_addr.s_node,
148 LOG(log_info, logtype_atalkd, "rtmp_config configured %s", iface->i_name );
149 iface->i_flags |= IFACE_CONFIG;
150 if ( iface == ciface ) {
151 ciface = ciface->i_next;
159 * Delete rtmp from the per-interface in-use table, remove all
160 * zone references, and remove the route from the kernel.
162 static void rtmp_delinuse(struct rtmptab *rtmp)
166 irt = rtmp->rt_gate->g_iface->i_rt;
167 if ( irt->rt_inext == rtmp ) { /* first */
168 if ( rtmp->rt_iprev == rtmp ) { /* only */
169 irt->rt_inext = NULL;
171 irt->rt_inext = rtmp->rt_inext;
172 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
175 if ( rtmp->rt_inext == NULL ) { /* last */
176 rtmp->rt_iprev->rt_inext = NULL;
177 irt->rt_inext->rt_iprev = rtmp->rt_iprev;
179 rtmp->rt_iprev->rt_inext = rtmp->rt_inext;
180 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
183 rtmp->rt_iprev = NULL;
184 rtmp->rt_inext = NULL;
186 /* remove zone map */
187 rtmp_delzonemap(rtmp);
189 /* remove old route */
190 gateroute( RTMP_DEL, rtmp );
194 * Add rtmp to the per-interface in-use table. No verification is done...
196 static void rtmp_addinuse( struct rtmptab *rtmp)
200 gateroute( RTMP_ADD, rtmp );
202 irt = rtmp->rt_gate->g_iface->i_rt;
203 if ( irt->rt_inext == NULL ) { /* empty list */
204 rtmp->rt_inext = NULL;
205 rtmp->rt_iprev = rtmp;
206 irt->rt_inext = rtmp;
208 rtmp->rt_inext = irt->rt_inext;
209 rtmp->rt_iprev = irt->rt_inext->rt_iprev;
210 irt->rt_inext->rt_iprev = rtmp;
211 irt->rt_inext = rtmp;
217 * Change the zone mapping to replace "from" with "to". This code assumes
218 * the consistency of both the route -> zone map and the zone -> route map.
219 * This is probably a bad idea. How can we insure that the data is good
220 * at this point? What do we do if we get several copies of a route in
223 static int rtmp_copyzones( struct rtmptab *to,struct rtmptab *from)
225 struct list *lz, *lr;
227 to->rt_zt = from->rt_zt;
229 if ( from->rt_flags & RTMPTAB_HASZONES ) {
230 to->rt_flags |= RTMPTAB_HASZONES;
232 for ( lz = to->rt_zt; lz; lz = lz->l_next ) {
233 for ( lr = ((struct ziptab *)lz->l_data)->zt_rt; lr; lr = lr->l_next ) {
234 if ( (struct rtmptab *)lr->l_data == from ) {
235 lr->l_data = (void *)to; /* cast BS */
240 LOG(log_error, logtype_atalkd, "rtmp_copyzones z -> r without r -> z, abort" );
250 * Remove rtmp from the in-use table and the per-gate table.
251 * Free any associated space.
253 void rtmp_free( struct rtmptab *rtmp)
257 LOG(log_info, logtype_atalkd, "rtmp_free: %u-%u", ntohs(rtmp->rt_firstnet),
258 ntohs(rtmp->rt_lastnet));
259 if ( rtmp->rt_iprev ) {
260 rtmp_delinuse( rtmp );
263 /* remove from per-gate */
264 gate = rtmp->rt_gate;
265 if ( gate->g_rt == rtmp ) { /* first */
266 if ( rtmp->rt_prev == rtmp ) { /* only */
269 gate->g_rt = rtmp->rt_next;
270 rtmp->rt_next->rt_prev = rtmp->rt_prev;
273 if ( rtmp->rt_next == NULL ) { /* last */
274 rtmp->rt_prev->rt_next = NULL;
275 gate->g_rt->rt_prev = rtmp->rt_prev;
277 rtmp->rt_prev->rt_next = rtmp->rt_next;
278 rtmp->rt_next->rt_prev = rtmp->rt_prev;
287 * Find a replacement for "replace". If we can't find a replacement,
288 * return 1. If we do find a replacement, return 0. -1 on error.
290 int rtmp_replace(struct rtmptab *replace)
292 struct interface *iface;
294 struct rtmptab *rtmp, *found = NULL;
296 LOG(log_info, logtype_atalkd, "rtmp_replace %u-%u", ntohs(replace->rt_firstnet),
297 ntohs(replace->rt_lastnet));
298 for ( iface = interfaces; iface; iface = iface->i_next ) {
299 if ((replace->rt_iface != iface) &&
300 ((iface->i_flags & IFACE_ISROUTER) == 0))
303 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
304 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
305 if ( rtmp->rt_firstnet == replace->rt_firstnet &&
306 rtmp->rt_lastnet == replace->rt_lastnet ) {
307 if ( found == NULL || rtmp->rt_hops < found->rt_hops ) {
316 if ( found != replace ) {
317 if (rtmp_copyzones( found, replace ) < 0)
319 rtmp_delinuse( replace );
320 rtmp_addinuse( found );
321 if ( replace->rt_state == RTMPTAB_BAD ) {
322 rtmp_free( replace );
326 if ( replace->rt_hops == RTMPHOPS_POISON ) {
327 gateroute( RTMP_DEL, replace );
334 static int rtmp_new(struct rtmptab *rtmp)
338 extern int newrtmpdata;
343 * Do we already have a gateway for this route?
345 for ( i = interfaces; i; i = i->i_next ) {
346 if ((rtmp->rt_iface != i) &&
347 ((i->i_flags & IFACE_ISROUTER) == 0))
350 for ( r = i->i_rt; r; r = r->rt_inext ) {
351 /* Should check RTMPTAB_EXTENDED here. XXX */
352 if (( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_firstnet ) &&
353 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_firstnet )) ||
354 ( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_lastnet ) &&
355 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_lastnet ))) {
365 * This part of this routine is almost never run.
367 if ( i ) { /* can we get here without r being set? */
368 if ( r->rt_firstnet != rtmp->rt_firstnet ||
369 r->rt_lastnet != rtmp->rt_lastnet ) {
370 LOG(log_info, logtype_atalkd, "rtmp_new netrange mismatch %u-%u != %u-%u",
371 ntohs( r->rt_firstnet ), ntohs( r->rt_lastnet ),
372 ntohs( rtmp->rt_firstnet ), ntohs( rtmp->rt_lastnet ));
377 * Note that our whole methodology is wrong, if we want to do
378 * route "load balancing." This entails changing our route
379 * each time we receive a tuple of equal value. In fact, we can't
380 * do this, using our method, since we only check against in-use
381 * routes when a tuple is new from a router.
383 if ( r->rt_hops < rtmp->rt_hops ) {
387 if (rtmp_copyzones( rtmp, r ) < 0)
392 rtmp_addinuse( rtmp );
397 int rtmp_packet(struct atport *ap, struct sockaddr_at *from, char *data, int len)
400 struct rtmp_tuple rt, xrt;
402 struct interface *iface;
403 struct rtmptab *rtmp;
404 char *end, packet[ ATP_BUFSIZ ];
410 LOG(log_info, logtype_atalkd, "rtmp_packet no data" );
414 iface = ap->ap_iface;
416 /* ignore our own packets */
417 if ( from->sat_addr.s_net == iface->i_addr.sat_addr.s_net &&
418 from->sat_addr.s_node == iface->i_addr.sat_addr.s_node ) {
423 case DDPTYPE_RTMPRD :
427 if ( data + sizeof( struct rtmprdhdr ) > end ) {
428 LOG(log_info, logtype_atalkd, "rtmp_packet no data header" );
431 memcpy( &rh, data, sizeof( struct rtmprdhdr ));
432 data += sizeof( struct rtmprdhdr );
434 /* check rh address against from address */
435 if ( rh.rh_nodelen != 8 ) {
436 LOG(log_info, logtype_atalkd, "rtmp_packet bad node len (%d)", rh.rh_nodelen );
439 if (( from->sat_addr.s_net != 0 &&
440 from->sat_addr.s_net != rh.rh_net ) ||
441 from->sat_addr.s_node != rh.rh_node ) {
442 LOG(log_info, logtype_atalkd, "rtmp_packet address mismatch" );
446 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG )) == IFACE_ADDR ) {
447 if ( iface->i_flags & IFACE_NOROUTER ) {
448 /* remove addr to loopback route */
449 if ((cc = looproute( iface, RTMP_DEL )) < 0) {
450 LOG(log_error, logtype_atalkd, "rtmp_packet: looproute");
455 LOG(log_error, logtype_atalkd, "rtmp_packet: can't remove loopback: %s",
458 iface->i_flags &= ~IFACE_NOROUTER;
460 LOG(log_info, logtype_atalkd, "rtmp_packet router has become available" );
462 if ( iface->i_flags & IFACE_PHASE1 ) {
463 if (rtmp_config( &rh, iface ) < 0) {
464 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_config");
467 } else if (zip_getnetinfo( iface ) < 0) {
468 LOG(log_error, logtype_atalkd, "rtmp_packet: zip_getnetinfo");
474 if (( iface->i_flags & IFACE_CONFIG ) == 0 ) {
479 * Parse first tuple. For phase 2, verify that net is correct.
481 if ( data + SZ_RTMPTUPLE > end ) {
482 LOG(log_info, logtype_atalkd, "rtmp_packet missing first tuple" );
485 memcpy( &rt, data, SZ_RTMPTUPLE );
486 data += SZ_RTMPTUPLE;
488 if ( rt.rt_net == 0 ) {
489 if ( rt.rt_dist != 0x82 ) {
490 LOG(log_info, logtype_atalkd, "rtmp_packet bad phase 1 version" );
495 * Grab the next tuple, since we don't want to pass the version
496 * number to the parsing code. We're assuming that there are
497 * no extended tuples in this packet.
499 if ( data + SZ_RTMPTUPLE > end ) {
500 LOG(log_info, logtype_atalkd, "rtmp_packet missing second tuple" );
503 memcpy( &rt, data, SZ_RTMPTUPLE );
504 data += SZ_RTMPTUPLE;
505 } else if ( rt.rt_dist & 0x80 ) {
506 if ( data + SZ_RTMPTUPLE > end ) {
507 LOG(log_info, logtype_atalkd, "rtmp_packet missing first range-end" );
510 memcpy( &xrt, data, SZ_RTMPTUPLE );
511 data += SZ_RTMPTUPLE;
513 if ( xrt.rt_dist != 0x82 ) {
514 LOG(log_info, logtype_atalkd, "rtmp_packet bad phase 2 version" );
519 * Check for net range conflict.
521 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
522 xrt.rt_net != iface->i_rt->rt_lastnet ) {
523 LOG(log_info, logtype_atalkd, "rtmp_packet interface mismatch" );
529 * Gatorboxes put a net number in the first tuple, even on
530 * phase 1 nets. This is wrong, but since we've got it, we
531 * might just as well check it.
532 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
533 rt.rt_net != iface->i_rt->rt_lastnet ) {
534 LOG(log_info, logtype_atalkd, "rtmp_packet phase 1 interface mismatch" );
538 #else /* PHASE1NET */
539 LOG(log_info, logtype_atalkd, "rtmp_packet bad first tuple" );
541 #endif /* PHASE1NET */
547 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
548 if ( gate->g_sat.sat_addr.s_net == from->sat_addr.s_net &&
549 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
553 if ( !gate ) { /* new gateway */
554 if (( gate = (struct gate *)malloc( sizeof( struct gate ))) == NULL ) {
555 LOG(log_error, logtype_atalkd, "rtmp_packet: malloc: %s", strerror(errno) );
558 gate->g_next = iface->i_gate;
561 gate->g_iface = iface; /* need this? */
563 if ( iface->i_gate ) {
564 iface->i_gate->g_prev = gate;
566 iface->i_gate = gate;
567 LOG(log_info, logtype_atalkd, "rtmp_packet gateway %u.%u up",
568 ntohs( gate->g_sat.sat_addr.s_net ),
569 gate->g_sat.sat_addr.s_node );
573 * Reset the timeout on this gateway. We'll remove the gateway
574 * entry, if the timeout gets to RTMPTAB_BAD.
576 gate->g_state = RTMPTAB_GOOD;
579 * Parse remaining tuples.
583 * Is route on this gateway?
585 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
586 if ( ntohs( rtmp->rt_firstnet ) <= ntohs( rt.rt_net ) &&
587 ntohs( rtmp->rt_lastnet ) >= ntohs( rt.rt_net )) {
590 if (( rt.rt_dist & 0x80 ) &&
591 ntohs( rtmp->rt_firstnet ) <= ntohs( xrt.rt_net ) &&
592 ntohs( rtmp->rt_lastnet ) >= ntohs( xrt.rt_net )) {
597 if ( rtmp ) { /* found it */
599 * Check for range conflicts. (This is getting a little
602 if ( rtmp->rt_firstnet != rt.rt_net ) {
603 LOG(log_info, logtype_atalkd, "rtmp_packet firstnet mismatch %u!=%u",
604 ntohs( rtmp->rt_firstnet ), ntohs( rt.rt_net ));
607 if ( rt.rt_dist & 0x80 ) {
608 if (( rtmp->rt_flags & RTMPTAB_EXTENDED ) == 0 ) {
609 LOG(log_info, logtype_atalkd, "rtmp_packet extended mismatch %u",
610 ntohs( rtmp->rt_firstnet ));
613 if ( rtmp->rt_lastnet != xrt.rt_net ) {
614 LOG(log_info, logtype_atalkd, "rtmp_packet lastnet mismatch %u!=%u",
615 ntohs( rtmp->rt_lastnet ), ntohs( xrt.rt_net ));
619 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
620 LOG(log_info, logtype_atalkd, "rtmp_packet !extended mismatch %u",
621 ntohs( rtmp->rt_firstnet ));
624 if ( rtmp->rt_lastnet != rt.rt_net ) {
625 LOG(log_info, logtype_atalkd, "rtmp_packet lastnet mismatch %u!=%u",
626 ntohs( rtmp->rt_lastnet ), ntohs( rt.rt_net ));
631 rtmp->rt_state = RTMPTAB_GOOD;
634 * Check hop count. If the count has changed, update
635 * the routing database.
637 if (( rtmp->rt_hops != ( rt.rt_dist & 0x7f ) + 1 ) &&
638 ( rtmp->rt_hops != RTMPHOPS_POISON ||
639 ( rt.rt_dist & 0x7f ) + 1 <= RTMPHOPS_MAX )) {
640 if ( rtmp->rt_iprev ) { /* route is in use */
641 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
643 * If this was POISON, we've deleted it from
644 * the kernel. Add it back in.
646 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
647 gateroute( RTMP_ADD, rtmp );
649 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
652 * Hop count has gone up for this route.
653 * Search for a new best route. If we can't
654 * find one, just keep this route. "poison"
655 * route are deleted in as_timer().
657 if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
658 rtmp->rt_hops = RTMPHOPS_POISON;
660 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
662 if (rtmp_replace( rtmp ) < 0) {
663 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_replace");
667 } else { /* route not in use */
668 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
669 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
670 if (rtmp_new( rtmp ) < 0) {
671 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_new");
679 * Make the *next* node the head, since
680 * we're not likely to be asked for the same tuple twice
683 if ( rtmp->rt_next != NULL ) {
684 gate->g_rt->rt_prev->rt_next = gate->g_rt;
685 gate->g_rt = rtmp->rt_next;
686 rtmp->rt_next = NULL;
688 } else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
689 LOG(log_info, logtype_atalkd, "rtmp_packet bad hop count from %u.%u for %u",
690 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
692 } else { /* new for router */
693 if (( rtmp = newrt(iface)) == NULL ) {
694 LOG(log_error, logtype_atalkd, "rtmp_packet: newrt: %s", strerror(errno) );
697 rtmp->rt_firstnet = rt.rt_net;
698 if ( rt.rt_dist & 0x80 ) {
699 rtmp->rt_lastnet = xrt.rt_net;
700 rtmp->rt_flags = RTMPTAB_EXTENDED;
702 rtmp->rt_lastnet = rt.rt_net;
704 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
705 rtmp->rt_state = RTMPTAB_GOOD;
706 rtmp->rt_gate = gate;
709 * Add rtmptab entry to end of list (leave head alone).
711 if ( gate->g_rt == NULL ) {
712 rtmp->rt_prev = rtmp;
715 rtmp->rt_prev = gate->g_rt->rt_prev;
716 gate->g_rt->rt_prev->rt_next = rtmp;
717 gate->g_rt->rt_prev = rtmp;
720 if (rtmp_new( rtmp ) < 0) {
721 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_new");
726 if ( data + SZ_RTMPTUPLE > end ) {
729 memcpy( &rt, data, SZ_RTMPTUPLE );
730 data += SZ_RTMPTUPLE;
731 if ( rt.rt_dist & 0x80 ) {
732 if ( data + SZ_RTMPTUPLE > end ) {
733 LOG(log_info, logtype_atalkd, "rtmp_packet missing range-end" );
736 memcpy( &xrt, data, SZ_RTMPTUPLE );
737 data += SZ_RTMPTUPLE;
742 * Make sure we've processed the whole packet.
745 LOG(log_info, logtype_atalkd, "rtmp_packet length and count mismatch" );
753 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
754 iface->i_rt->rt_zt == NULL ||
755 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
760 *data++ = DDPTYPE_RTMPRD;
761 rh.rh_net = iface->i_addr.sat_addr.s_net;
763 rh.rh_node = iface->i_addr.sat_addr.s_node;
764 memcpy( data, &rh, sizeof( struct rtmp_head ));
765 data += sizeof( struct rtmp_head );
767 if ( iface->i_flags & IFACE_PHASE2 ) {
768 rt.rt_net = iface->i_rt->rt_firstnet;
770 memcpy( data, &rt, SZ_RTMPTUPLE );
771 data += SZ_RTMPTUPLE;
773 rt.rt_net = iface->i_rt->rt_lastnet;
775 memcpy( data, &rt, SZ_RTMPTUPLE );
776 data += SZ_RTMPTUPLE;
778 if ( sendto( ap->ap_fd, packet, data - packet, 0,
779 (struct sockaddr *)from,
780 sizeof( struct sockaddr_at )) < 0 ) {
781 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
783 } else if ( *data == 2 || *data == 3 ) {
785 printf( "rtmp_packet rdr (%d) from %u.%u\n",
786 *data, ntohs( from->sat_addr.s_net ),
787 from->sat_addr.s_node );
790 LOG(log_info, logtype_atalkd, "rtmp_packet unknown request from %u.%u",
791 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
796 LOG(log_info, logtype_atalkd, "rtmp_packet bad ddp type from %u.%u",
797 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
804 int rtmp_request( struct interface *iface)
806 struct sockaddr_at sat;
808 char *data, packet[ 2 ];
810 LOG(log_info, logtype_atalkd, "rtmp_request for %s", iface->i_name );
812 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
813 if ( ap->ap_packet == rtmp_packet ) {
818 LOG(log_error, logtype_atalkd, "rtmp_request can't find rtmp socket!" );
823 *data++ = DDPTYPE_RTMPR;
824 *data++ = RTMPROP_REQUEST;
827 * There is a problem with the net zero "hint" hack.
829 memset( &sat, 0, sizeof( struct sockaddr_at ));
831 sat.sat_len = sizeof( struct sockaddr_at );
833 sat.sat_family = AF_APPLETALK;
834 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
835 sat.sat_addr.s_node = ATADDR_BCAST;
836 sat.sat_port = ap->ap_port;
837 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
838 sizeof( struct sockaddr_at )) < 0 ) {
839 LOG(log_error, logtype_atalkd, "rtmp_request sendto: %s", strerror(errno) );
846 int looproute(struct interface *iface, unsigned int cmd)
848 struct sockaddr_at dst, loop;
850 if ( cmd == RTMP_DEL && ( iface->i_flags & IFACE_LOOP ) == 0 ) {
851 LOG(log_error, logtype_atalkd, "looproute panic no route" );
855 if ( cmd == RTMP_ADD && ( iface->i_flags & IFACE_LOOP )) {
856 LOG(log_error, logtype_atalkd, "looproute panic two routes" );
860 memset( &dst, 0, sizeof( struct sockaddr_at ));
862 dst.sat_len = sizeof( struct sockaddr_at );
864 dst.sat_family = AF_APPLETALK;
865 dst.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
866 dst.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
867 memset( &loop, 0, sizeof( struct sockaddr_at ));
869 loop.sat_len = sizeof( struct sockaddr_at );
871 loop.sat_family = AF_APPLETALK;
872 loop.sat_addr.s_net = htons( ATADDR_ANYNET );
873 loop.sat_addr.s_node = ATADDR_ANYNODE;
877 (struct sockaddr *) &dst,
878 (struct sockaddr *) &loop,
879 RTF_UP | RTF_HOST ) ) {
884 (struct sockaddr_at *) &dst,
885 (struct sockaddr_at *) &loop,
886 RTF_UP | RTF_HOST ) ) {
890 if ( cmd == RTMP_ADD ) {
891 iface->i_flags |= IFACE_LOOP;
893 if ( cmd == RTMP_DEL ) {
894 iface->i_flags &= ~IFACE_LOOP;
899 int gateroute(unsigned int command, struct rtmptab *rtmp)
901 struct sockaddr_at dst, gate;
904 if ( command == RTMP_DEL && ( rtmp->rt_flags & RTMPTAB_ROUTE ) == 0 ) {
907 if ( command == RTMP_ADD && ( rtmp->rt_flags & RTMPTAB_ROUTE )) {
911 net = ntohs( rtmp->rt_firstnet );
913 * Since we will accept routes from gateways who advertise their
914 * address as 0.YY, we must munge the gateway address we give to
915 * the kernel. Otherwise, we'll get a bunch of routes to the loop
916 * back interface, and who wants that?
918 memset( &gate, 0, sizeof( struct sockaddr_at ));
920 gate.sat_len = sizeof( struct sockaddr_at );
922 gate.sat_family = AF_APPLETALK;
923 gate.sat_addr.s_net = rtmp->rt_gate->g_sat.sat_addr.s_net;
924 gate.sat_addr.s_node = rtmp->rt_gate->g_sat.sat_addr.s_node;
925 if ( gate.sat_addr.s_net == 0 ) {
926 gate.sat_addr.s_net = net;
929 memset( &dst, 0, sizeof( struct sockaddr_at ));
931 dst.sat_len = sizeof( struct sockaddr_at );
933 dst.sat_family = AF_APPLETALK;
934 dst.sat_addr.s_node = ATADDR_ANYNODE;
937 dst.sat_addr.s_net = htons( net );
940 (struct sockaddr *) &dst,
941 (struct sockaddr *) &gate,
942 RTF_UP | RTF_GATEWAY )) {
943 LOG(log_error, logtype_atalkd, "route: %u -> %u.%u: %s", net,
944 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node,
950 (struct sockaddr_at *) &dst,
951 (struct sockaddr_at *) &gate,
952 RTF_UP | RTF_GATEWAY )) {
953 LOG(log_error, logtype_atalkd, "route: %u -> %u.%u: %s", net,
954 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node, strerror(errno) );
957 #endif /* ! BSD4_4 */
958 } while ( net++ < ntohs( rtmp->rt_lastnet ));
960 if ( command == RTMP_ADD ) {
961 rtmp->rt_flags |= RTMPTAB_ROUTE;
963 if ( command == RTMP_DEL ) {
964 rtmp->rt_flags &= ~RTMPTAB_ROUTE;
971 newrt(const struct interface *iface)
973 struct rtmptab *rtmp;
975 if (( rtmp = (struct rtmptab *)calloc(1, sizeof(struct rtmptab))) == NULL ) {
979 rtmp->rt_iface = iface;