2 * $Id: rtmp.c,v 1.8 2001-08-15 01:39:39 srittau Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
14 #include <sys/syslog.h>
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <sys/socket.h>
18 #include <sys/ioctl.h>
21 #include <net/route.h>
24 #include <net/route.h>
25 #include <netatalk/endian.h>
26 #include <netatalk/at.h>
29 #include <sys/sockio.h>
32 #include <atalk/ddp.h>
33 #include <atalk/atp.h>
34 #include <atalk/rtmp.h>
36 #include "interface.h"
45 void rtmp_delzonemap(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( rh, iface )
100 struct rtmp_head *rh;
101 struct interface *iface;
103 extern int stabletimer;
107 * If we're configuring a phase 2 interface, don't complete
108 * configuration with RTMP.
110 if ( iface->i_flags & IFACE_PHASE2 ) {
111 syslog( LOG_INFO, "rtmp_config ignoring data" );
116 * Check our seed information, and reconfigure.
118 if ( rh->rh_net != iface->i_addr.sat_addr.s_net ) {
119 if (( iface->i_flags & IFACE_SEED ) &&
120 rh->rh_net != iface->i_caddr.sat_addr.s_net) {
121 syslog( LOG_ERR, "rtmp_config net mismatch %u != %u",
123 ntohs( iface->i_addr.sat_addr.s_net ));
126 iface->i_addr.sat_addr.s_net = rh->rh_net;
129 * It is possible that we will corrupt our route database
130 * by just forcing this change. XXX
132 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = rh->rh_net;
134 setaddr( iface, IFACE_PHASE1, iface->i_addr.sat_addr.s_net,
135 iface->i_addr.sat_addr.s_node, rh->rh_net, rh->rh_net );
136 stabletimer = UNSTABLE;
139 /* add addr to loopback route */
140 if ((cc = looproute( iface, RTMP_ADD )) < 0 )
144 syslog( LOG_ERR, "rtmp_config: can't route %u.%u to loopback: %m",
145 ntohs( iface->i_addr.sat_addr.s_net ),
146 iface->i_addr.sat_addr.s_node );
149 syslog( LOG_INFO, "rtmp_config configured %s", iface->i_name );
150 iface->i_flags |= IFACE_CONFIG;
151 if ( iface == ciface ) {
152 ciface = ciface->i_next;
160 * Delete rtmp from the per-interface in-use table, remove all
161 * zone references, and remove the route from the kernel.
163 static void rtmp_delinuse( rtmp )
164 struct rtmptab *rtmp;
168 irt = rtmp->rt_gate->g_iface->i_rt;
169 if ( irt->rt_inext == rtmp ) { /* first */
170 if ( rtmp->rt_iprev == rtmp ) { /* only */
171 irt->rt_inext = NULL;
173 irt->rt_inext = rtmp->rt_inext;
174 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
177 if ( rtmp->rt_inext == NULL ) { /* last */
178 rtmp->rt_iprev->rt_inext = NULL;
179 irt->rt_inext->rt_iprev = rtmp->rt_iprev;
181 rtmp->rt_iprev->rt_inext = rtmp->rt_inext;
182 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
185 rtmp->rt_iprev = NULL;
186 rtmp->rt_inext = NULL;
188 /* remove zone map */
189 rtmp_delzonemap(rtmp);
191 /* remove old route */
192 gateroute( RTMP_DEL, rtmp );
196 * Add rtmp to the per-interface in-use table. No verification is done...
198 static void rtmp_addinuse( rtmp )
199 struct rtmptab *rtmp;
203 gateroute( RTMP_ADD, rtmp );
205 irt = rtmp->rt_gate->g_iface->i_rt;
206 if ( irt->rt_inext == NULL ) { /* empty list */
207 rtmp->rt_inext = NULL;
208 rtmp->rt_iprev = rtmp;
209 irt->rt_inext = rtmp;
211 rtmp->rt_inext = irt->rt_inext;
212 rtmp->rt_iprev = irt->rt_inext->rt_iprev;
213 irt->rt_inext->rt_iprev = rtmp;
214 irt->rt_inext = rtmp;
220 * Change the zone mapping to replace "from" with "to". This code assumes
221 * the consistency of both the route -> zone map and the zone -> route map.
222 * This is probably a bad idea. How can we insure that the data is good
223 * at this point? What do we do if we get several copies of a route in
226 static int rtmp_copyzones( to, from )
227 struct rtmptab *to, *from;
229 struct list *lz, *lr;
231 to->rt_zt = from->rt_zt;
233 if ( from->rt_flags & RTMPTAB_HASZONES ) {
234 to->rt_flags |= RTMPTAB_HASZONES;
236 for ( lz = to->rt_zt; lz; lz = lz->l_next ) {
237 for ( lr = ((struct ziptab *)lz->l_data)->zt_rt; lr; lr = lr->l_next ) {
238 if ( (struct rtmptab *)lr->l_data == from ) {
239 lr->l_data = (void *)to; /* cast BS */
244 syslog( LOG_ERR, "rtmp_copyzones z -> r without r -> z, abort" );
254 * Remove rtmp from the in-use table and the per-gate table.
255 * Free any associated space.
257 void rtmp_free( rtmp )
258 struct rtmptab *rtmp;
262 syslog(LOG_INFO, "rtmp_free: %u-%u", ntohs(rtmp->rt_firstnet),
263 ntohs(rtmp->rt_lastnet));
264 if ( rtmp->rt_iprev ) {
265 rtmp_delinuse( rtmp );
268 /* remove from per-gate */
269 gate = rtmp->rt_gate;
270 if ( gate->g_rt == rtmp ) { /* first */
271 if ( rtmp->rt_prev == rtmp ) { /* only */
274 gate->g_rt = rtmp->rt_next;
275 rtmp->rt_next->rt_prev = rtmp->rt_prev;
278 if ( rtmp->rt_next == NULL ) { /* last */
279 rtmp->rt_prev->rt_next = NULL;
280 gate->g_rt->rt_prev = rtmp->rt_prev;
282 rtmp->rt_prev->rt_next = rtmp->rt_next;
283 rtmp->rt_next->rt_prev = rtmp->rt_prev;
292 * Find a replacement for "replace". If we can't find a replacement,
293 * return 1. If we do find a replacement, return 0. -1 on error.
295 int rtmp_replace( replace )
296 struct rtmptab *replace;
298 struct interface *iface;
300 struct rtmptab *rtmp, *found = NULL;
302 syslog(LOG_INFO, "rtmp_replace %u-%u", ntohs(replace->rt_firstnet),
303 ntohs(replace->rt_lastnet));
304 for ( iface = interfaces; iface; iface = iface->i_next ) {
305 if ((replace->rt_iface != iface) &&
306 ((iface->i_flags & IFACE_ISROUTER) == 0))
309 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
310 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
311 if ( rtmp->rt_firstnet == replace->rt_firstnet &&
312 rtmp->rt_lastnet == replace->rt_lastnet ) {
313 if ( found == NULL || rtmp->rt_hops < found->rt_hops ) {
322 if ( found != replace ) {
323 if (rtmp_copyzones( found, replace ) < 0)
325 rtmp_delinuse( replace );
326 rtmp_addinuse( found );
327 if ( replace->rt_state == RTMPTAB_BAD ) {
328 rtmp_free( replace );
332 if ( replace->rt_hops == RTMPHOPS_POISON ) {
333 gateroute( RTMP_DEL, replace );
340 static int rtmp_new( rtmp )
341 struct rtmptab *rtmp;
345 extern int newrtmpdata;
350 * Do we already have a gateway for this route?
352 for ( i = interfaces; i; i = i->i_next ) {
353 if ((rtmp->rt_iface != i) &&
354 ((i->i_flags & IFACE_ISROUTER) == 0))
357 for ( r = i->i_rt; r; r = r->rt_inext ) {
358 /* Should check RTMPTAB_EXTENDED here. XXX */
359 if (( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_firstnet ) &&
360 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_firstnet )) ||
361 ( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_lastnet ) &&
362 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_lastnet ))) {
372 * This part of this routine is almost never run.
374 if ( i ) { /* can we get here without r being set? */
375 if ( r->rt_firstnet != rtmp->rt_firstnet ||
376 r->rt_lastnet != rtmp->rt_lastnet ) {
377 syslog( LOG_INFO, "rtmp_new netrange mismatch %u-%u != %u-%u",
378 ntohs( r->rt_firstnet ), ntohs( r->rt_lastnet ),
379 ntohs( rtmp->rt_firstnet ), ntohs( rtmp->rt_lastnet ));
384 * Note that our whole methodology is wrong, if we want to do
385 * route "load balancing." This entails changing our route
386 * each time we receive a tuple of equal value. In fact, we can't
387 * do this, using our method, since we only check against in-use
388 * routes when a tuple is new from a router.
390 if ( r->rt_hops < rtmp->rt_hops ) {
394 if (rtmp_copyzones( rtmp, r ) < 0)
399 rtmp_addinuse( rtmp );
404 int rtmp_packet( ap, from, data, len )
406 struct sockaddr_at *from;
411 struct rtmp_tuple rt, xrt;
413 struct interface *iface;
414 struct rtmptab *rtmp;
415 char *end, packet[ ATP_BUFSIZ ];
421 syslog( LOG_INFO, "rtmp_packet no data" );
425 iface = ap->ap_iface;
427 /* ignore our own packets */
428 if ( from->sat_addr.s_net == iface->i_addr.sat_addr.s_net &&
429 from->sat_addr.s_node == iface->i_addr.sat_addr.s_node ) {
434 case DDPTYPE_RTMPRD :
438 if ( data + sizeof( struct rtmprdhdr ) > end ) {
439 syslog( LOG_INFO, "rtmp_packet no data header" );
442 memcpy( &rh, data, sizeof( struct rtmprdhdr ));
443 data += sizeof( struct rtmprdhdr );
445 /* check rh address against from address */
446 if ( rh.rh_nodelen != 8 ) {
447 syslog( LOG_INFO, "rtmp_packet bad node len (%d)", rh.rh_nodelen );
450 if (( from->sat_addr.s_net != 0 &&
451 from->sat_addr.s_net != rh.rh_net ) ||
452 from->sat_addr.s_node != rh.rh_node ) {
453 syslog( LOG_INFO, "rtmp_packet address mismatch" );
457 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG )) == IFACE_ADDR ) {
458 if ( iface->i_flags & IFACE_NOROUTER ) {
459 /* remove addr to loopback route */
460 if ((cc = looproute( iface, RTMP_DEL )) < 0) {
461 syslog(LOG_ERR, "rtmp_packet: looproute");
466 syslog( LOG_ERR, "rtmp_packet: can't remove loopback: %m" );
468 iface->i_flags &= ~IFACE_NOROUTER;
470 syslog( LOG_INFO, "rtmp_packet router has become available" );
472 if ( iface->i_flags & IFACE_PHASE1 ) {
473 if (rtmp_config( &rh, iface ) < 0) {
474 syslog(LOG_ERR, "rtmp_packet: rtmp_config");
477 } else if (zip_getnetinfo( iface ) < 0) {
478 syslog(LOG_ERR, "rtmp_packet: zip_getnetinfo");
484 if (( iface->i_flags & IFACE_CONFIG ) == 0 ) {
489 * Parse first tuple. For phase 2, verify that net is correct.
491 if ( data + SZ_RTMPTUPLE > end ) {
492 syslog( LOG_INFO, "rtmp_packet missing first tuple" );
495 memcpy( &rt, data, SZ_RTMPTUPLE );
496 data += SZ_RTMPTUPLE;
498 if ( rt.rt_net == 0 ) {
499 if ( rt.rt_dist != 0x82 ) {
500 syslog( LOG_INFO, "rtmp_packet bad phase 1 version" );
505 * Grab the next tuple, since we don't want to pass the version
506 * number to the parsing code. We're assuming that there are
507 * no extended tuples in this packet.
509 if ( data + SZ_RTMPTUPLE > end ) {
510 syslog( LOG_INFO, "rtmp_packet missing second tuple" );
513 memcpy( &rt, data, SZ_RTMPTUPLE );
514 data += SZ_RTMPTUPLE;
515 } else if ( rt.rt_dist & 0x80 ) {
516 if ( data + SZ_RTMPTUPLE > end ) {
517 syslog( LOG_INFO, "rtmp_packet missing first range-end" );
520 memcpy( &xrt, data, SZ_RTMPTUPLE );
521 data += SZ_RTMPTUPLE;
523 if ( xrt.rt_dist != 0x82 ) {
524 syslog( LOG_INFO, "rtmp_packet bad phase 2 version" );
529 * Check for net range conflict.
531 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
532 xrt.rt_net != iface->i_rt->rt_lastnet ) {
533 syslog( LOG_INFO, "rtmp_packet interface mismatch" );
539 * Gatorboxes put a net number in the first tuple, even on
540 * phase 1 nets. This is wrong, but since we've got it, we
541 * might just as well check it.
542 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
543 rt.rt_net != iface->i_rt->rt_lastnet ) {
544 syslog( LOG_INFO, "rtmp_packet phase 1 interface mismatch" );
548 #else /* PHASE1NET */
549 syslog( LOG_INFO, "rtmp_packet bad first tuple" );
551 #endif /* PHASE1NET */
557 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
558 if ( gate->g_sat.sat_addr.s_net == from->sat_addr.s_net &&
559 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
563 if ( !gate ) { /* new gateway */
564 if (( gate = (struct gate *)malloc( sizeof( struct gate ))) == 0 ) {
565 syslog( LOG_ERR, "rtmp_packet: malloc: %m" );
568 gate->g_next = iface->i_gate;
571 gate->g_iface = iface; /* need this? */
573 if ( iface->i_gate ) {
574 iface->i_gate->g_prev = gate;
576 iface->i_gate = gate;
577 syslog( LOG_INFO, "rtmp_packet gateway %u.%u up",
578 ntohs( gate->g_sat.sat_addr.s_net ),
579 gate->g_sat.sat_addr.s_node );
583 * Reset the timeout on this gateway. We'll remove the gateway
584 * entry, if the timeout gets to RTMPTAB_BAD.
586 gate->g_state = RTMPTAB_GOOD;
589 * Parse remaining tuples.
593 * Is route on this gateway?
595 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
596 if ( ntohs( rtmp->rt_firstnet ) <= ntohs( rt.rt_net ) &&
597 ntohs( rtmp->rt_lastnet ) >= ntohs( rt.rt_net )) {
600 if (( rt.rt_dist & 0x80 ) &&
601 ntohs( rtmp->rt_firstnet ) <= ntohs( xrt.rt_net ) &&
602 ntohs( rtmp->rt_lastnet ) >= ntohs( xrt.rt_net )) {
607 if ( rtmp ) { /* found it */
609 * Check for range conflicts. (This is getting a little
612 if ( rtmp->rt_firstnet != rt.rt_net ) {
613 syslog( LOG_INFO, "rtmp_packet firstnet mismatch %u!=%u",
614 ntohs( rtmp->rt_firstnet ), ntohs( rt.rt_net ));
617 if ( rt.rt_dist & 0x80 ) {
618 if (( rtmp->rt_flags & RTMPTAB_EXTENDED ) == 0 ) {
619 syslog( LOG_INFO, "rtmp_packet extended mismatch %u",
620 ntohs( rtmp->rt_firstnet ));
623 if ( rtmp->rt_lastnet != xrt.rt_net ) {
624 syslog( LOG_INFO, "rtmp_packet lastnet mismatch %u!=%u",
625 ntohs( rtmp->rt_lastnet ), ntohs( xrt.rt_net ));
629 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
630 syslog( LOG_INFO, "rtmp_packet !extended mismatch %u",
631 ntohs( rtmp->rt_firstnet ));
634 if ( rtmp->rt_lastnet != rt.rt_net ) {
635 syslog( LOG_INFO, "rtmp_packet lastnet mismatch %u!=%u",
636 ntohs( rtmp->rt_lastnet ), ntohs( rt.rt_net ));
641 rtmp->rt_state = RTMPTAB_GOOD;
644 * Check hop count. If the count has changed, update
645 * the routing database.
647 if (( rtmp->rt_hops != ( rt.rt_dist & 0x7f ) + 1 ) &&
648 ( rtmp->rt_hops != RTMPHOPS_POISON ||
649 ( rt.rt_dist & 0x7f ) + 1 <= RTMPHOPS_MAX )) {
650 if ( rtmp->rt_iprev ) { /* route is in use */
651 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
653 * If this was POISON, we've deleted it from
654 * the kernel. Add it back in.
656 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
657 gateroute( RTMP_ADD, rtmp );
659 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
662 * Hop count has gone up for this route.
663 * Search for a new best route. If we can't
664 * find one, just keep this route. "poison"
665 * route are deleted in as_timer().
667 if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
668 rtmp->rt_hops = RTMPHOPS_POISON;
670 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
672 if (rtmp_replace( rtmp ) < 0) {
673 syslog(LOG_ERR, "rtmp_packet: rtmp_replace");
677 } else { /* route not in use */
678 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
679 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
680 if (rtmp_new( rtmp ) < 0) {
681 syslog(LOG_ERR, "rtmp_packet: rtmp_new");
689 * Make the *next* node the head, since
690 * we're not likely to be asked for the same tuple twice
693 if ( rtmp->rt_next != 0 ) {
694 gate->g_rt->rt_prev->rt_next = gate->g_rt;
695 gate->g_rt = rtmp->rt_next;
698 } else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
699 syslog( LOG_INFO, "rtmp_packet bad hop count from %u.%u for %u",
700 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
702 } else { /* new for router */
703 if (( rtmp = newrt(iface)) == NULL ) {
704 syslog( LOG_ERR, "rtmp_packet: newrt: %m" );
707 rtmp->rt_firstnet = rt.rt_net;
708 if ( rt.rt_dist & 0x80 ) {
709 rtmp->rt_lastnet = xrt.rt_net;
710 rtmp->rt_flags = RTMPTAB_EXTENDED;
712 rtmp->rt_lastnet = rt.rt_net;
714 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
715 rtmp->rt_state = RTMPTAB_GOOD;
716 rtmp->rt_gate = gate;
719 * Add rtmptab entry to end of list (leave head alone).
721 if ( gate->g_rt == 0 ) {
722 rtmp->rt_prev = rtmp;
725 rtmp->rt_prev = gate->g_rt->rt_prev;
726 gate->g_rt->rt_prev->rt_next = rtmp;
727 gate->g_rt->rt_prev = rtmp;
730 if (rtmp_new( rtmp ) < 0) {
731 syslog(LOG_ERR, "rtmp_packet: rtmp_new");
736 if ( data + SZ_RTMPTUPLE > end ) {
739 memcpy( &rt, data, SZ_RTMPTUPLE );
740 data += SZ_RTMPTUPLE;
741 if ( rt.rt_dist & 0x80 ) {
742 if ( data + SZ_RTMPTUPLE > end ) {
743 syslog( LOG_INFO, "rtmp_packet missing range-end" );
746 memcpy( &xrt, data, SZ_RTMPTUPLE );
747 data += SZ_RTMPTUPLE;
752 * Make sure we've processed the whole packet.
755 syslog( LOG_INFO, "rtmp_packet length and count mismatch" );
763 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
764 iface->i_rt->rt_zt == 0 ||
765 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
770 *data++ = DDPTYPE_RTMPRD;
771 rh.rh_net = iface->i_addr.sat_addr.s_net;
773 rh.rh_node = iface->i_addr.sat_addr.s_node;
774 memcpy( data, &rh, sizeof( struct rtmp_head ));
775 data += sizeof( struct rtmp_head );
777 if ( iface->i_flags & IFACE_PHASE2 ) {
778 rt.rt_net = iface->i_rt->rt_firstnet;
780 memcpy( data, &rt, SZ_RTMPTUPLE );
781 data += SZ_RTMPTUPLE;
783 rt.rt_net = iface->i_rt->rt_lastnet;
785 memcpy( data, &rt, SZ_RTMPTUPLE );
786 data += SZ_RTMPTUPLE;
788 if ( sendto( ap->ap_fd, packet, data - packet, 0,
789 (struct sockaddr *)from,
790 sizeof( struct sockaddr_at )) < 0 ) {
791 syslog( LOG_ERR, "as_timer sendto: %m" );
793 } else if ( *data == 2 || *data == 3 ) {
795 printf( "rtmp_packet rdr (%d) from %u.%u\n",
796 *data, ntohs( from->sat_addr.s_net ),
797 from->sat_addr.s_node );
800 syslog( LOG_INFO, "rtmp_packet unknown request from %u.%u\n",
801 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
806 syslog( LOG_INFO, "rtmp_packet bad ddp type from %u.%u",
807 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
814 int rtmp_request( iface )
815 struct interface *iface;
817 struct sockaddr_at sat;
819 char *data, packet[ 2 ];
821 syslog( LOG_INFO, "rtmp_request for %s", iface->i_name );
823 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
824 if ( ap->ap_packet == rtmp_packet ) {
829 syslog( LOG_ERR, "rtmp_request can't find rtmp socket!" );
834 *data++ = DDPTYPE_RTMPR;
835 *data++ = RTMPROP_REQUEST;
838 * There is a problem with the net zero "hint" hack.
840 memset( &sat, 0, sizeof( struct sockaddr_at ));
842 sat.sat_len = sizeof( struct sockaddr_at );
844 sat.sat_family = AF_APPLETALK;
845 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
846 sat.sat_addr.s_node = ATADDR_BCAST;
847 sat.sat_port = ap->ap_port;
848 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
849 sizeof( struct sockaddr_at )) < 0 ) {
850 syslog( LOG_ERR, "rtmp_request sendto: %m" );
857 int looproute( iface, cmd )
858 struct interface *iface;
861 struct sockaddr_at dst, loop;
863 if ( cmd == RTMP_DEL && ( iface->i_flags & IFACE_LOOP ) == 0 ) {
864 syslog( LOG_ERR, "looproute panic no route" );
868 if ( cmd == RTMP_ADD && ( iface->i_flags & IFACE_LOOP )) {
869 syslog( LOG_ERR, "looproute panic two routes" );
873 memset( &dst, 0, sizeof( struct sockaddr_at ));
875 dst.sat_len = sizeof( struct sockaddr_at );
877 dst.sat_family = AF_APPLETALK;
878 dst.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
879 dst.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
880 memset( &loop, 0, sizeof( struct sockaddr_at ));
882 loop.sat_len = sizeof( struct sockaddr_at );
884 loop.sat_family = AF_APPLETALK;
885 loop.sat_addr.s_net = htons( ATADDR_ANYNET );
886 loop.sat_addr.s_node = ATADDR_ANYNODE;
890 (struct sockaddr *) &dst,
891 (struct sockaddr *) &loop,
892 RTF_UP | RTF_HOST ) ) {
897 (struct sockaddr_at *) &dst,
898 (struct sockaddr_at *) &loop,
899 RTF_UP | RTF_HOST ) ) {
903 if ( cmd == RTMP_ADD ) {
904 iface->i_flags |= IFACE_LOOP;
906 if ( cmd == RTMP_DEL ) {
907 iface->i_flags &= ~IFACE_LOOP;
912 int gateroute( command, rtmp )
913 unsigned int command;
914 struct rtmptab *rtmp;
916 struct sockaddr_at dst, gate;
919 if ( command == RTMP_DEL && ( rtmp->rt_flags & RTMPTAB_ROUTE ) == 0 ) {
922 if ( command == RTMP_ADD && ( rtmp->rt_flags & RTMPTAB_ROUTE )) {
926 net = ntohs( rtmp->rt_firstnet );
928 * Since we will accept routes from gateways who advertise their
929 * address as 0.YY, we must munge the gateway address we give to
930 * the kernel. Otherwise, we'll get a bunch of routes to the loop
931 * back interface, and who wants that?
933 memset( &gate, 0, sizeof( struct sockaddr_at ));
935 gate.sat_len = sizeof( struct sockaddr_at );
937 gate.sat_family = AF_APPLETALK;
938 gate.sat_addr.s_net = rtmp->rt_gate->g_sat.sat_addr.s_net;
939 gate.sat_addr.s_node = rtmp->rt_gate->g_sat.sat_addr.s_node;
940 if ( gate.sat_addr.s_net == 0 ) {
941 gate.sat_addr.s_net = net;
944 memset( &dst, 0, sizeof( struct sockaddr_at ));
946 dst.sat_len = sizeof( struct sockaddr_at );
948 dst.sat_family = AF_APPLETALK;
949 dst.sat_addr.s_node = ATADDR_ANYNODE;
952 dst.sat_addr.s_net = htons( net );
955 (struct sockaddr *) &dst,
956 (struct sockaddr *) &gate,
957 RTF_UP | RTF_GATEWAY )) {
958 syslog( LOG_ERR, "route: %u -> %u.%u: %m", net,
959 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
964 (struct sockaddr_at *) &dst,
965 (struct sockaddr_at *) &gate,
966 RTF_UP | RTF_GATEWAY )) {
967 syslog( LOG_ERR, "route: %u -> %u.%u: %m", net,
968 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
971 #endif /* ! BSD4_4 */
972 } while ( net++ < ntohs( rtmp->rt_lastnet ));
974 if ( command == RTMP_ADD ) {
975 rtmp->rt_flags |= RTMPTAB_ROUTE;
977 if ( command == RTMP_DEL ) {
978 rtmp->rt_flags &= ~RTMPTAB_ROUTE;
985 newrt(const struct interface *iface)
987 struct rtmptab *rtmp;
989 if (( rtmp = (struct rtmptab *)calloc(1, sizeof(struct rtmptab))) == 0 ) {
993 rtmp->rt_iface = iface;