2 * $Id: rtmp.c,v 1.17 2009-12-08 03:21:16 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 interface *iface2;
404 struct rtmptab *rtmp;
405 char *end, packet[ ATP_BUFSIZ ];
411 LOG(log_info, logtype_atalkd, "rtmp_packet no data" );
415 iface = ap->ap_iface;
417 /* linux 2.6 sends broadcast queries to the first available socket
418 (in our case the last configured)
419 try to find the right one.
420 Note: now a misconfigured or plugged router can broadcast
423 for ( iface2 = interfaces; iface2; iface2 = iface2->i_next ) {
424 if ( iface2->i_rt && from->sat_addr.s_net >= iface2->i_rt->rt_firstnet &&
425 from->sat_addr.s_net <= iface2->i_rt->rt_lastnet)
430 /* end of linux 2.6 workaround */
432 /* ignore our own packets */
433 if ( from->sat_addr.s_net == iface->i_addr.sat_addr.s_net &&
434 from->sat_addr.s_node == iface->i_addr.sat_addr.s_node ) {
439 case DDPTYPE_RTMPRD :
443 if ( data + sizeof( struct rtmprdhdr ) > end ) {
444 LOG(log_info, logtype_atalkd, "rtmp_packet no data header" );
447 memcpy( &rh, data, sizeof( struct rtmprdhdr ));
448 data += sizeof( struct rtmprdhdr );
450 /* check rh address against from address */
451 if ( rh.rh_nodelen != 8 ) {
452 LOG(log_info, logtype_atalkd, "rtmp_packet bad node len (%d)", rh.rh_nodelen );
455 if (( from->sat_addr.s_net != 0 &&
456 from->sat_addr.s_net != rh.rh_net ) ||
457 from->sat_addr.s_node != rh.rh_node ) {
458 LOG(log_info, logtype_atalkd, "rtmp_packet address mismatch" );
462 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG )) == IFACE_ADDR ) {
463 if ( iface->i_flags & IFACE_NOROUTER ) {
464 /* remove addr to loopback route */
465 if ((cc = looproute( iface, RTMP_DEL )) < 0) {
466 LOG(log_error, logtype_atalkd, "rtmp_packet: looproute");
471 LOG(log_error, logtype_atalkd, "rtmp_packet: can't remove loopback: %s",
474 iface->i_flags &= ~IFACE_NOROUTER;
476 LOG(log_info, logtype_atalkd, "rtmp_packet router has become available" );
478 if ( iface->i_flags & IFACE_PHASE1 ) {
479 if (rtmp_config( &rh, iface ) < 0) {
480 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_config");
483 } else if (zip_getnetinfo( iface ) < 0) {
484 LOG(log_error, logtype_atalkd, "rtmp_packet: zip_getnetinfo");
490 if (( iface->i_flags & IFACE_CONFIG ) == 0 ) {
495 * Parse first tuple. For phase 2, verify that net is correct.
497 if ( data + SZ_RTMPTUPLE > end ) {
498 LOG(log_info, logtype_atalkd, "rtmp_packet missing first tuple" );
501 memcpy( &rt, data, SZ_RTMPTUPLE );
502 data += SZ_RTMPTUPLE;
504 if ( rt.rt_net == 0 ) {
505 if ( rt.rt_dist != 0x82 ) {
506 LOG(log_info, logtype_atalkd, "rtmp_packet bad phase 1 version" );
511 * Grab the next tuple, since we don't want to pass the version
512 * number to the parsing code. We're assuming that there are
513 * no extended tuples in this packet.
515 if ( data + SZ_RTMPTUPLE > end ) {
516 LOG(log_info, logtype_atalkd, "rtmp_packet missing second tuple" );
519 memcpy( &rt, data, SZ_RTMPTUPLE );
520 data += SZ_RTMPTUPLE;
521 } else if ( rt.rt_dist & 0x80 ) {
522 if ( data + SZ_RTMPTUPLE > end ) {
523 LOG(log_info, logtype_atalkd, "rtmp_packet missing first range-end" );
526 memcpy( &xrt, data, SZ_RTMPTUPLE );
527 data += SZ_RTMPTUPLE;
529 if ( xrt.rt_dist != 0x82 ) {
530 LOG(log_info, logtype_atalkd, "rtmp_packet bad phase 2 version" );
535 * Check for net range conflict.
537 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
538 xrt.rt_net != iface->i_rt->rt_lastnet ) {
539 LOG(log_info, logtype_atalkd, "rtmp_packet interface mismatch" );
545 * Gatorboxes put a net number in the first tuple, even on
546 * phase 1 nets. This is wrong, but since we've got it, we
547 * might just as well check it.
548 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
549 rt.rt_net != iface->i_rt->rt_lastnet ) {
550 LOG(log_info, logtype_atalkd, "rtmp_packet phase 1 interface mismatch" );
554 #else /* PHASE1NET */
555 LOG(log_info, logtype_atalkd, "rtmp_packet bad first tuple" );
557 #endif /* PHASE1NET */
563 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
564 if ( gate->g_sat.sat_addr.s_net == from->sat_addr.s_net &&
565 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
569 if ( !gate ) { /* new gateway */
570 if (( gate = (struct gate *)malloc( sizeof( struct gate ))) == NULL ) {
571 LOG(log_error, logtype_atalkd, "rtmp_packet: malloc: %s", strerror(errno) );
574 gate->g_next = iface->i_gate;
577 gate->g_iface = iface; /* need this? */
579 if ( iface->i_gate ) {
580 iface->i_gate->g_prev = gate;
582 iface->i_gate = gate;
583 LOG(log_info, logtype_atalkd, "rtmp_packet gateway %u.%u up",
584 ntohs( gate->g_sat.sat_addr.s_net ),
585 gate->g_sat.sat_addr.s_node );
589 * Reset the timeout on this gateway. We'll remove the gateway
590 * entry, if the timeout gets to RTMPTAB_BAD.
592 gate->g_state = RTMPTAB_GOOD;
595 * Parse remaining tuples.
599 * Is route on this gateway?
601 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
602 if ( ntohs( rtmp->rt_firstnet ) <= ntohs( rt.rt_net ) &&
603 ntohs( rtmp->rt_lastnet ) >= ntohs( rt.rt_net )) {
606 if (( rt.rt_dist & 0x80 ) &&
607 ntohs( rtmp->rt_firstnet ) <= ntohs( xrt.rt_net ) &&
608 ntohs( rtmp->rt_lastnet ) >= ntohs( xrt.rt_net )) {
613 if ( rtmp ) { /* found it */
615 * Check for range conflicts. (This is getting a little
618 if ( rtmp->rt_firstnet != rt.rt_net ) {
619 LOG(log_info, logtype_atalkd, "rtmp_packet firstnet mismatch %u!=%u",
620 ntohs( rtmp->rt_firstnet ), ntohs( rt.rt_net ));
623 if ( rt.rt_dist & 0x80 ) {
624 if (( rtmp->rt_flags & RTMPTAB_EXTENDED ) == 0 ) {
625 LOG(log_info, logtype_atalkd, "rtmp_packet extended mismatch %u",
626 ntohs( rtmp->rt_firstnet ));
629 if ( rtmp->rt_lastnet != xrt.rt_net ) {
630 LOG(log_info, logtype_atalkd, "rtmp_packet lastnet mismatch %u!=%u",
631 ntohs( rtmp->rt_lastnet ), ntohs( xrt.rt_net ));
635 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
636 LOG(log_info, logtype_atalkd, "rtmp_packet !extended mismatch %u",
637 ntohs( rtmp->rt_firstnet ));
640 if ( rtmp->rt_lastnet != rt.rt_net ) {
641 LOG(log_info, logtype_atalkd, "rtmp_packet lastnet mismatch %u!=%u",
642 ntohs( rtmp->rt_lastnet ), ntohs( rt.rt_net ));
647 rtmp->rt_state = RTMPTAB_GOOD;
650 * Check hop count. If the count has changed, update
651 * the routing database.
653 if (( rtmp->rt_hops != ( rt.rt_dist & 0x7f ) + 1 ) &&
654 ( rtmp->rt_hops != RTMPHOPS_POISON ||
655 ( rt.rt_dist & 0x7f ) + 1 <= RTMPHOPS_MAX )) {
656 if ( rtmp->rt_iprev ) { /* route is in use */
657 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
659 * If this was POISON, we've deleted it from
660 * the kernel. Add it back in.
662 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
663 gateroute( RTMP_ADD, rtmp );
665 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
668 * Hop count has gone up for this route.
669 * Search for a new best route. If we can't
670 * find one, just keep this route. "poison"
671 * route are deleted in as_timer().
673 if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
674 rtmp->rt_hops = RTMPHOPS_POISON;
676 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
678 if (rtmp_replace( rtmp ) < 0) {
679 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_replace");
683 } else { /* route not in use */
684 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
685 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
686 if (rtmp_new( rtmp ) < 0) {
687 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_new");
695 * Make the *next* node the head, since
696 * we're not likely to be asked for the same tuple twice
699 if ( rtmp->rt_next != NULL ) {
700 gate->g_rt->rt_prev->rt_next = gate->g_rt;
701 gate->g_rt = rtmp->rt_next;
702 rtmp->rt_next = NULL;
704 } else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
705 LOG(log_info, logtype_atalkd, "rtmp_packet bad hop count from %u.%u for %u",
706 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
708 } else { /* new for router */
709 if (( rtmp = newrt(iface)) == NULL ) {
710 LOG(log_error, logtype_atalkd, "rtmp_packet: newrt: %s", strerror(errno) );
713 rtmp->rt_firstnet = rt.rt_net;
714 if ( rt.rt_dist & 0x80 ) {
715 rtmp->rt_lastnet = xrt.rt_net;
716 rtmp->rt_flags = RTMPTAB_EXTENDED;
718 rtmp->rt_lastnet = rt.rt_net;
720 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
721 rtmp->rt_state = RTMPTAB_GOOD;
722 rtmp->rt_gate = gate;
725 * Add rtmptab entry to end of list (leave head alone).
727 if ( gate->g_rt == NULL ) {
728 rtmp->rt_prev = rtmp;
731 rtmp->rt_prev = gate->g_rt->rt_prev;
732 gate->g_rt->rt_prev->rt_next = rtmp;
733 gate->g_rt->rt_prev = rtmp;
736 if (rtmp_new( rtmp ) < 0) {
737 LOG(log_error, logtype_atalkd, "rtmp_packet: rtmp_new");
742 if ( data + SZ_RTMPTUPLE > end ) {
745 memcpy( &rt, data, SZ_RTMPTUPLE );
746 data += SZ_RTMPTUPLE;
747 if ( rt.rt_dist & 0x80 ) {
748 if ( data + SZ_RTMPTUPLE > end ) {
749 LOG(log_info, logtype_atalkd, "rtmp_packet missing range-end" );
752 memcpy( &xrt, data, SZ_RTMPTUPLE );
753 data += SZ_RTMPTUPLE;
758 * Make sure we've processed the whole packet.
761 LOG(log_info, logtype_atalkd, "rtmp_packet length and count mismatch" );
769 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
770 iface->i_rt->rt_zt == NULL ||
771 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
776 *data++ = DDPTYPE_RTMPRD;
777 rh.rh_net = iface->i_addr.sat_addr.s_net;
779 rh.rh_node = iface->i_addr.sat_addr.s_node;
780 memcpy( data, &rh, sizeof( struct rtmp_head ));
781 data += sizeof( struct rtmp_head );
783 if ( iface->i_flags & IFACE_PHASE2 ) {
784 rt.rt_net = iface->i_rt->rt_firstnet;
786 memcpy( data, &rt, SZ_RTMPTUPLE );
787 data += SZ_RTMPTUPLE;
789 rt.rt_net = iface->i_rt->rt_lastnet;
791 memcpy( data, &rt, SZ_RTMPTUPLE );
792 data += SZ_RTMPTUPLE;
794 if ( sendto( ap->ap_fd, packet, data - packet, 0,
795 (struct sockaddr *)from,
796 sizeof( struct sockaddr_at )) < 0 ) {
797 LOG(log_error, logtype_atalkd, "as_timer sendto: %s", strerror(errno) );
799 } else if ( *data == 2 || *data == 3 ) {
801 printf( "rtmp_packet rdr (%d) from %u.%u\n",
802 *data, ntohs( from->sat_addr.s_net ),
803 from->sat_addr.s_node );
806 LOG(log_info, logtype_atalkd, "rtmp_packet unknown request from %u.%u",
807 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
812 LOG(log_info, logtype_atalkd, "rtmp_packet bad ddp type from %u.%u",
813 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
820 int rtmp_request( struct interface *iface)
822 struct sockaddr_at sat;
824 char *data, packet[ 2 ];
826 LOG(log_info, logtype_atalkd, "rtmp_request for %s", iface->i_name );
828 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
829 if ( ap->ap_packet == rtmp_packet ) {
834 LOG(log_error, logtype_atalkd, "rtmp_request can't find rtmp socket!" );
839 *data++ = DDPTYPE_RTMPR;
840 *data++ = RTMPROP_REQUEST;
843 * There is a problem with the net zero "hint" hack.
845 memset( &sat, 0, sizeof( struct sockaddr_at ));
847 sat.sat_len = sizeof( struct sockaddr_at );
849 sat.sat_family = AF_APPLETALK;
850 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
851 sat.sat_addr.s_node = ATADDR_BCAST;
852 sat.sat_port = ap->ap_port;
853 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
854 sizeof( struct sockaddr_at )) < 0 ) {
855 LOG(log_error, logtype_atalkd, "rtmp_request sendto: %s", strerror(errno) );
862 int looproute(struct interface *iface, unsigned int cmd)
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(unsigned int command, struct rtmptab *rtmp)
917 struct sockaddr_at dst, gate;
920 if ( command == RTMP_DEL && ( rtmp->rt_flags & RTMPTAB_ROUTE ) == 0 ) {
923 if ( command == RTMP_ADD && ( rtmp->rt_flags & RTMPTAB_ROUTE )) {
927 net = ntohs( rtmp->rt_firstnet );
929 * Since we will accept routes from gateways who advertise their
930 * address as 0.YY, we must munge the gateway address we give to
931 * the kernel. Otherwise, we'll get a bunch of routes to the loop
932 * back interface, and who wants that?
934 memset( &gate, 0, sizeof( struct sockaddr_at ));
936 gate.sat_len = sizeof( struct sockaddr_at );
938 gate.sat_family = AF_APPLETALK;
939 gate.sat_addr.s_net = rtmp->rt_gate->g_sat.sat_addr.s_net;
940 gate.sat_addr.s_node = rtmp->rt_gate->g_sat.sat_addr.s_node;
941 if ( gate.sat_addr.s_net == 0 ) {
942 gate.sat_addr.s_net = net;
945 memset( &dst, 0, sizeof( struct sockaddr_at ));
947 dst.sat_len = sizeof( struct sockaddr_at );
949 dst.sat_family = AF_APPLETALK;
950 dst.sat_addr.s_node = ATADDR_ANYNODE;
953 dst.sat_addr.s_net = htons( net );
956 (struct sockaddr *) &dst,
957 (struct sockaddr *) &gate,
958 RTF_UP | RTF_GATEWAY )) {
959 LOG(log_error, logtype_atalkd, "route: %u -> %u.%u: %s", net,
960 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node,
966 (struct sockaddr_at *) &dst,
967 (struct sockaddr_at *) &gate,
968 RTF_UP | RTF_GATEWAY )) {
969 LOG(log_error, logtype_atalkd, "route: %u -> %u.%u: %s", net,
970 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node, strerror(errno) );
973 #endif /* ! BSD4_4 */
974 } while ( net++ < ntohs( rtmp->rt_lastnet ));
976 if ( command == RTMP_ADD ) {
977 rtmp->rt_flags |= RTMPTAB_ROUTE;
979 if ( command == RTMP_DEL ) {
980 rtmp->rt_flags &= ~RTMPTAB_ROUTE;
987 newrt(const struct interface *iface)
989 struct rtmptab *rtmp;
991 if (( rtmp = (struct rtmptab *)calloc(1, sizeof(struct rtmptab))) == NULL ) {
995 rtmp->rt_iface = iface;