2 * $Id: rtmp.c,v 1.5 2001-06-19 18:04:39 rufustfirefly 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>
20 #include <net/route.h>
21 #include <netatalk/endian.h>
22 #include <netatalk/at.h>
25 #include <sys/sockio.h>
28 #include <atalk/ddp.h>
29 #include <atalk/atp.h>
30 #include <atalk/rtmp.h>
32 #include "interface.h"
41 void rtmp_delzonemap(rtmp)
44 struct list *lz, *flz, *lr, *flr;
48 while ( lz ) { /* for each zone */
49 zt = (struct ziptab *)lz->l_data;
51 while ( lr ) { /* for each route */
52 if ( (struct rtmptab *)lr->l_data == rtmp ) {
53 if ( lr->l_prev == NULL ) { /* head */
54 if ( lr->l_next == NULL ) { /* last route in zone */
55 if ( zt->zt_prev == NULL ) {
58 zt->zt_prev->zt_next = zt->zt_next;
60 if ( zt->zt_next == NULL ) {
61 ziplast = zt->zt_prev;
63 zt->zt_next->zt_prev = zt->zt_prev;
69 zt->zt_rt = lr->l_next;
72 lr->l_prev->l_next = lr->l_next;
74 if ( lr->l_next != NULL ) {
75 lr->l_next->l_prev = lr->l_prev;
93 * Complete configuration for phase 1 interface using RTMP information.
95 static int rtmp_config( rh, iface )
97 struct interface *iface;
99 extern int stabletimer;
103 * If we're configuring a phase 2 interface, don't complete
104 * configuration with RTMP.
106 if ( iface->i_flags & IFACE_PHASE2 ) {
107 syslog( LOG_INFO, "rtmp_config ignoring data" );
112 * Check our seed information, and reconfigure.
114 if ( rh->rh_net != iface->i_addr.sat_addr.s_net ) {
115 if (( iface->i_flags & IFACE_SEED ) &&
116 rh->rh_net != iface->i_caddr.sat_addr.s_net) {
117 syslog( LOG_ERR, "rtmp_config net mismatch %u != %u",
119 ntohs( iface->i_addr.sat_addr.s_net ));
122 iface->i_addr.sat_addr.s_net = rh->rh_net;
125 * It is possible that we will corrupt our route database
126 * by just forcing this change. XXX
128 iface->i_rt->rt_firstnet = iface->i_rt->rt_lastnet = rh->rh_net;
130 setaddr( iface, IFACE_PHASE1, iface->i_addr.sat_addr.s_net,
131 iface->i_addr.sat_addr.s_node, rh->rh_net, rh->rh_net );
132 stabletimer = UNSTABLE;
135 /* add addr to loopback route */
136 if ((cc = looproute( iface, RTMP_ADD )) < 0 )
140 syslog( LOG_ERR, "rtmp_config: can't route %u.%u to loopback: %m",
141 ntohs( iface->i_addr.sat_addr.s_net ),
142 iface->i_addr.sat_addr.s_node );
145 syslog( LOG_INFO, "rtmp_config configured %s", iface->i_name );
146 iface->i_flags |= IFACE_CONFIG;
147 if ( iface == ciface ) {
148 ciface = ciface->i_next;
156 * Delete rtmp from the per-interface in-use table, remove all
157 * zone references, and remove the route from the kernel.
159 static void rtmp_delinuse( rtmp )
160 struct rtmptab *rtmp;
164 irt = rtmp->rt_gate->g_iface->i_rt;
165 if ( irt->rt_inext == rtmp ) { /* first */
166 if ( rtmp->rt_iprev == rtmp ) { /* only */
167 irt->rt_inext = NULL;
169 irt->rt_inext = rtmp->rt_inext;
170 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
173 if ( rtmp->rt_inext == NULL ) { /* last */
174 rtmp->rt_iprev->rt_inext = NULL;
175 irt->rt_inext->rt_iprev = rtmp->rt_iprev;
177 rtmp->rt_iprev->rt_inext = rtmp->rt_inext;
178 rtmp->rt_inext->rt_iprev = rtmp->rt_iprev;
181 rtmp->rt_iprev = NULL;
182 rtmp->rt_inext = NULL;
184 /* remove zone map */
185 rtmp_delzonemap(rtmp);
187 /* remove old route */
188 gateroute( RTMP_DEL, rtmp );
192 * Add rtmp to the per-interface in-use table. No verification is done...
194 static void rtmp_addinuse( rtmp )
195 struct rtmptab *rtmp;
199 gateroute( RTMP_ADD, rtmp );
201 irt = rtmp->rt_gate->g_iface->i_rt;
202 if ( irt->rt_inext == NULL ) { /* empty list */
203 rtmp->rt_inext = NULL;
204 rtmp->rt_iprev = rtmp;
205 irt->rt_inext = rtmp;
207 rtmp->rt_inext = irt->rt_inext;
208 rtmp->rt_iprev = irt->rt_inext->rt_iprev;
209 irt->rt_inext->rt_iprev = rtmp;
210 irt->rt_inext = rtmp;
216 * Change the zone mapping to replace "from" with "to". This code assumes
217 * the consistency of both the route -> zone map and the zone -> route map.
218 * This is probably a bad idea. How can we insure that the data is good
219 * at this point? What do we do if we get several copies of a route in
222 static int rtmp_copyzones( to, from )
223 struct rtmptab *to, *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 syslog( LOG_ERR, "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( rtmp )
254 struct rtmptab *rtmp;
258 syslog(LOG_INFO, "rtmp_free: %u-%u", ntohs(rtmp->rt_firstnet),
259 ntohs(rtmp->rt_lastnet));
260 if ( rtmp->rt_iprev ) {
261 rtmp_delinuse( rtmp );
264 /* remove from per-gate */
265 gate = rtmp->rt_gate;
266 if ( gate->g_rt == rtmp ) { /* first */
267 if ( rtmp->rt_prev == rtmp ) { /* only */
270 gate->g_rt = rtmp->rt_next;
271 rtmp->rt_next->rt_prev = rtmp->rt_prev;
274 if ( rtmp->rt_next == NULL ) { /* last */
275 rtmp->rt_prev->rt_next = NULL;
276 gate->g_rt->rt_prev = rtmp->rt_prev;
278 rtmp->rt_prev->rt_next = rtmp->rt_next;
279 rtmp->rt_next->rt_prev = rtmp->rt_prev;
288 * Find a replacement for "replace". If we can't find a replacement,
289 * return 1. If we do find a replacement, return 0. -1 on error.
291 int rtmp_replace( replace )
292 struct rtmptab *replace;
294 struct interface *iface;
296 struct rtmptab *rtmp, *found = NULL;
298 syslog(LOG_INFO, "rtmp_replace %u-%u", ntohs(replace->rt_firstnet),
299 ntohs(replace->rt_lastnet));
300 for ( iface = interfaces; iface; iface = iface->i_next ) {
301 if ((replace->rt_iface != iface) &&
302 ((iface->i_flags & IFACE_ISROUTER) == 0))
305 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
306 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
307 if ( rtmp->rt_firstnet == replace->rt_firstnet &&
308 rtmp->rt_lastnet == replace->rt_lastnet ) {
309 if ( found == NULL || rtmp->rt_hops < found->rt_hops ) {
318 if ( found != replace ) {
319 if (rtmp_copyzones( found, replace ) < 0)
321 rtmp_delinuse( replace );
322 rtmp_addinuse( found );
323 if ( replace->rt_state == RTMPTAB_BAD ) {
324 rtmp_free( replace );
328 if ( replace->rt_hops == RTMPHOPS_POISON ) {
329 gateroute( RTMP_DEL, replace );
336 static int rtmp_new( rtmp )
337 struct rtmptab *rtmp;
341 extern int newrtmpdata;
346 * Do we already have a gateway for this route?
348 for ( i = interfaces; i; i = i->i_next ) {
349 if ((rtmp->rt_iface != i) &&
350 ((i->i_flags & IFACE_ISROUTER) == 0))
353 for ( r = i->i_rt; r; r = r->rt_inext ) {
354 /* Should check RTMPTAB_EXTENDED here. XXX */
355 if (( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_firstnet ) &&
356 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_firstnet )) ||
357 ( ntohs( r->rt_firstnet ) <= ntohs( rtmp->rt_lastnet ) &&
358 ntohs( r->rt_lastnet ) >= ntohs( rtmp->rt_lastnet ))) {
368 * This part of this routine is almost never run.
370 if ( i ) { /* can we get here without r being set? */
371 if ( r->rt_firstnet != rtmp->rt_firstnet ||
372 r->rt_lastnet != rtmp->rt_lastnet ) {
373 syslog( LOG_INFO, "rtmp_new netrange mismatch %u-%u != %u-%u",
374 ntohs( r->rt_firstnet ), ntohs( r->rt_lastnet ),
375 ntohs( rtmp->rt_firstnet ), ntohs( rtmp->rt_lastnet ));
380 * Note that our whole methodology is wrong, if we want to do
381 * route "load balancing." This entails changing our route
382 * each time we receive a tuple of equal value. In fact, we can't
383 * do this, using our method, since we only check against in-use
384 * routes when a tuple is new from a router.
386 if ( r->rt_hops < rtmp->rt_hops ) {
390 if (rtmp_copyzones( rtmp, r ) < 0)
395 rtmp_addinuse( rtmp );
400 int rtmp_packet( ap, from, data, len )
402 struct sockaddr_at *from;
407 struct rtmp_tuple rt, xrt;
409 struct interface *iface;
410 struct rtmptab *rtmp;
411 char *end, packet[ ATP_BUFSIZ ];
417 syslog( LOG_INFO, "rtmp_packet no data" );
421 iface = ap->ap_iface;
423 /* ignore our own packets */
424 if ( from->sat_addr.s_net == iface->i_addr.sat_addr.s_net &&
425 from->sat_addr.s_node == iface->i_addr.sat_addr.s_node ) {
430 case DDPTYPE_RTMPRD :
434 if ( data + sizeof( struct rtmprdhdr ) > end ) {
435 syslog( LOG_INFO, "rtmp_packet no data header" );
438 memcpy( &rh, data, sizeof( struct rtmprdhdr ));
439 data += sizeof( struct rtmprdhdr );
441 /* check rh address against from address */
442 if ( rh.rh_nodelen != 8 ) {
443 syslog( LOG_INFO, "rtmp_packet bad node len (%d)", rh.rh_nodelen );
446 if (( from->sat_addr.s_net != 0 &&
447 from->sat_addr.s_net != rh.rh_net ) ||
448 from->sat_addr.s_node != rh.rh_node ) {
449 syslog( LOG_INFO, "rtmp_packet address mismatch" );
453 if (( iface->i_flags & ( IFACE_ADDR|IFACE_CONFIG )) == IFACE_ADDR ) {
454 if ( iface->i_flags & IFACE_NOROUTER ) {
455 /* remove addr to loopback route */
456 if ((cc = looproute( iface, RTMP_DEL )) < 0) {
457 syslog(LOG_ERR, "rtmp_packet: looproute");
462 syslog( LOG_ERR, "rtmp_packet: can't remove loopback: %m" );
464 iface->i_flags &= ~IFACE_NOROUTER;
466 syslog( LOG_INFO, "rtmp_packet router has become available" );
468 if ( iface->i_flags & IFACE_PHASE1 ) {
469 if (rtmp_config( &rh, iface ) < 0) {
470 syslog(LOG_ERR, "rtmp_packet: rtmp_config");
473 } else if (zip_getnetinfo( iface ) < 0) {
474 syslog(LOG_ERR, "rtmp_packet: zip_getnetinfo");
480 if (( iface->i_flags & IFACE_CONFIG ) == 0 ) {
485 * Parse first tuple. For phase 2, verify that net is correct.
487 if ( data + SZ_RTMPTUPLE > end ) {
488 syslog( LOG_INFO, "rtmp_packet missing first tuple" );
491 memcpy( &rt, data, SZ_RTMPTUPLE );
492 data += SZ_RTMPTUPLE;
494 if ( rt.rt_net == 0 ) {
495 if ( rt.rt_dist != 0x82 ) {
496 syslog( LOG_INFO, "rtmp_packet bad phase 1 version" );
501 * Grab the next tuple, since we don't want to pass the version
502 * number to the parsing code. We're assuming that there are
503 * no extended tuples in this packet.
505 if ( data + SZ_RTMPTUPLE > end ) {
506 syslog( LOG_INFO, "rtmp_packet missing second tuple" );
509 memcpy( &rt, data, SZ_RTMPTUPLE );
510 data += SZ_RTMPTUPLE;
511 } else if ( rt.rt_dist & 0x80 ) {
512 if ( data + SZ_RTMPTUPLE > end ) {
513 syslog( LOG_INFO, "rtmp_packet missing first range-end" );
516 memcpy( &xrt, data, SZ_RTMPTUPLE );
517 data += SZ_RTMPTUPLE;
519 if ( xrt.rt_dist != 0x82 ) {
520 syslog( LOG_INFO, "rtmp_packet bad phase 2 version" );
525 * Check for net range conflict.
527 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
528 xrt.rt_net != iface->i_rt->rt_lastnet ) {
529 syslog( LOG_INFO, "rtmp_packet interface mismatch" );
535 * Gatorboxes put a net number in the first tuple, even on
536 * phase 1 nets. This is wrong, but since we've got it, we
537 * might just as well check it.
538 if ( rt.rt_net != iface->i_rt->rt_firstnet ||
539 rt.rt_net != iface->i_rt->rt_lastnet ) {
540 syslog( LOG_INFO, "rtmp_packet phase 1 interface mismatch" );
544 #else /* PHASE1NET */
545 syslog( LOG_INFO, "rtmp_packet bad first tuple" );
547 #endif /* PHASE1NET */
553 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
554 if ( gate->g_sat.sat_addr.s_net == from->sat_addr.s_net &&
555 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
559 if ( !gate ) { /* new gateway */
560 if (( gate = (struct gate *)malloc( sizeof( struct gate ))) == 0 ) {
561 syslog( LOG_ERR, "rtmp_packet: malloc: %m" );
564 gate->g_next = iface->i_gate;
567 gate->g_iface = iface; /* need this? */
569 if ( iface->i_gate ) {
570 iface->i_gate->g_prev = gate;
572 iface->i_gate = gate;
573 syslog( LOG_INFO, "rtmp_packet gateway %u.%u up",
574 ntohs( gate->g_sat.sat_addr.s_net ),
575 gate->g_sat.sat_addr.s_node );
579 * Reset the timeout on this gateway. We'll remove the gateway
580 * entry, if the timeout gets to RTMPTAB_BAD.
582 gate->g_state = RTMPTAB_GOOD;
585 * Parse remaining tuples.
589 * Is route on this gateway?
591 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
592 if ( ntohs( rtmp->rt_firstnet ) <= ntohs( rt.rt_net ) &&
593 ntohs( rtmp->rt_lastnet ) >= ntohs( rt.rt_net )) {
596 if (( rt.rt_dist & 0x80 ) &&
597 ntohs( rtmp->rt_firstnet ) <= ntohs( xrt.rt_net ) &&
598 ntohs( rtmp->rt_lastnet ) >= ntohs( xrt.rt_net )) {
603 if ( rtmp ) { /* found it */
605 * Check for range conflicts. (This is getting a little
608 if ( rtmp->rt_firstnet != rt.rt_net ) {
609 syslog( LOG_INFO, "rtmp_packet firstnet mismatch %u!=%u",
610 ntohs( rtmp->rt_firstnet ), ntohs( rt.rt_net ));
613 if ( rt.rt_dist & 0x80 ) {
614 if (( rtmp->rt_flags & RTMPTAB_EXTENDED ) == 0 ) {
615 syslog( LOG_INFO, "rtmp_packet extended mismatch %u",
616 ntohs( rtmp->rt_firstnet ));
619 if ( rtmp->rt_lastnet != xrt.rt_net ) {
620 syslog( LOG_INFO, "rtmp_packet lastnet mismatch %u!=%u",
621 ntohs( rtmp->rt_lastnet ), ntohs( xrt.rt_net ));
625 if ( rtmp->rt_flags & RTMPTAB_EXTENDED ) {
626 syslog( LOG_INFO, "rtmp_packet !extended mismatch %u",
627 ntohs( rtmp->rt_firstnet ));
630 if ( rtmp->rt_lastnet != rt.rt_net ) {
631 syslog( LOG_INFO, "rtmp_packet lastnet mismatch %u!=%u",
632 ntohs( rtmp->rt_lastnet ), ntohs( rt.rt_net ));
637 rtmp->rt_state = RTMPTAB_GOOD;
640 * Check hop count. If the count has changed, update
641 * the routing database.
643 if (( rtmp->rt_hops != ( rt.rt_dist & 0x7f ) + 1 ) &&
644 ( rtmp->rt_hops != RTMPHOPS_POISON ||
645 ( rt.rt_dist & 0x7f ) + 1 <= RTMPHOPS_MAX )) {
646 if ( rtmp->rt_iprev ) { /* route is in use */
647 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
649 * If this was POISON, we've deleted it from
650 * the kernel. Add it back in.
652 if ( rtmp->rt_hops == RTMPHOPS_POISON ) {
653 gateroute( RTMP_ADD, rtmp );
655 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
658 * Hop count has gone up for this route.
659 * Search for a new best route. If we can't
660 * find one, just keep this route. "poison"
661 * route are deleted in as_timer().
663 if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
664 rtmp->rt_hops = RTMPHOPS_POISON;
666 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
668 if (rtmp_replace( rtmp ) < 0) {
669 syslog(LOG_ERR, "rtmp_packet: rtmp_replace");
673 } else { /* route not in use */
674 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
675 if ( rtmp->rt_hops > ( rt.rt_dist & 0x7f ) + 1 ) {
676 if (rtmp_new( rtmp ) < 0) {
677 syslog(LOG_ERR, "rtmp_packet: rtmp_new");
685 * Make the *next* node the head, since
686 * we're not likely to be asked for the same tuple twice
689 if ( rtmp->rt_next != 0 ) {
690 gate->g_rt->rt_prev->rt_next = gate->g_rt;
691 gate->g_rt = rtmp->rt_next;
694 } else if (( rt.rt_dist & 0x7f ) + 1 > RTMPHOPS_MAX ) {
695 syslog( LOG_INFO, "rtmp_packet bad hop count from %u.%u for %u",
696 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
698 } else { /* new for router */
699 if (( rtmp = newrt(iface)) == NULL ) {
700 syslog( LOG_ERR, "rtmp_packet: newrt: %m" );
703 rtmp->rt_firstnet = rt.rt_net;
704 if ( rt.rt_dist & 0x80 ) {
705 rtmp->rt_lastnet = xrt.rt_net;
706 rtmp->rt_flags = RTMPTAB_EXTENDED;
708 rtmp->rt_lastnet = rt.rt_net;
710 rtmp->rt_hops = ( rt.rt_dist & 0x7f ) + 1;
711 rtmp->rt_state = RTMPTAB_GOOD;
712 rtmp->rt_gate = gate;
715 * Add rtmptab entry to end of list (leave head alone).
717 if ( gate->g_rt == 0 ) {
718 rtmp->rt_prev = rtmp;
721 rtmp->rt_prev = gate->g_rt->rt_prev;
722 gate->g_rt->rt_prev->rt_next = rtmp;
723 gate->g_rt->rt_prev = rtmp;
726 if (rtmp_new( rtmp ) < 0) {
727 syslog(LOG_ERR, "rtmp_packet: rtmp_new");
732 if ( data + SZ_RTMPTUPLE > end ) {
735 memcpy( &rt, data, SZ_RTMPTUPLE );
736 data += SZ_RTMPTUPLE;
737 if ( rt.rt_dist & 0x80 ) {
738 if ( data + SZ_RTMPTUPLE > end ) {
739 syslog( LOG_INFO, "rtmp_packet missing range-end" );
742 memcpy( &xrt, data, SZ_RTMPTUPLE );
743 data += SZ_RTMPTUPLE;
748 * Make sure we've processed the whole packet.
751 syslog( LOG_INFO, "rtmp_packet length and count mismatch" );
759 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
760 iface->i_rt->rt_zt == 0 ||
761 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
766 *data++ = DDPTYPE_RTMPRD;
767 rh.rh_net = iface->i_addr.sat_addr.s_net;
769 rh.rh_node = iface->i_addr.sat_addr.s_node;
770 memcpy( data, &rh, sizeof( struct rtmp_head ));
771 data += sizeof( struct rtmp_head );
773 if ( iface->i_flags & IFACE_PHASE2 ) {
774 rt.rt_net = iface->i_rt->rt_firstnet;
776 memcpy( data, &rt, SZ_RTMPTUPLE );
777 data += SZ_RTMPTUPLE;
779 rt.rt_net = iface->i_rt->rt_lastnet;
781 memcpy( data, &rt, SZ_RTMPTUPLE );
782 data += SZ_RTMPTUPLE;
784 if ( sendto( ap->ap_fd, packet, data - packet, 0,
785 (struct sockaddr *)from,
786 sizeof( struct sockaddr_at )) < 0 ) {
787 syslog( LOG_ERR, "as_timer sendto: %m" );
789 } else if ( *data == 2 || *data == 3 ) {
791 printf( "rtmp_packet rdr (%d) from %u.%u\n",
792 *data, ntohs( from->sat_addr.s_net ),
793 from->sat_addr.s_node );
796 syslog( LOG_INFO, "rtmp_packet unknown request from %u.%u\n",
797 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
802 syslog( LOG_INFO, "rtmp_packet bad ddp type from %u.%u",
803 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
810 int rtmp_request( iface )
811 struct interface *iface;
813 struct sockaddr_at sat;
815 char *data, packet[ 2 ];
817 syslog( LOG_INFO, "rtmp_request for %s", iface->i_name );
819 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
820 if ( ap->ap_packet == rtmp_packet ) {
825 syslog( LOG_ERR, "rtmp_request can't find rtmp socket!" );
830 *data++ = DDPTYPE_RTMPR;
831 *data++ = RTMPROP_REQUEST;
834 * There is a problem with the net zero "hint" hack.
836 memset( &sat, 0, sizeof( struct sockaddr_at ));
838 sat.sat_len = sizeof( struct sockaddr_at );
840 sat.sat_family = AF_APPLETALK;
841 sat.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
842 sat.sat_addr.s_node = ATADDR_BCAST;
843 sat.sat_port = ap->ap_port;
844 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
845 sizeof( struct sockaddr_at )) < 0 ) {
846 syslog( LOG_ERR, "rtmp_request sendto: %m" );
853 int looproute( iface, cmd )
854 struct interface *iface;
857 struct sockaddr_at dst, loop;
859 if ( cmd == RTMP_DEL && ( iface->i_flags & IFACE_LOOP ) == 0 ) {
860 syslog( LOG_ERR, "looproute panic no route" );
864 if ( cmd == RTMP_ADD && ( iface->i_flags & IFACE_LOOP )) {
865 syslog( LOG_ERR, "looproute panic two routes" );
869 memset( &dst, 0, sizeof( struct sockaddr_at ));
871 dst.sat_len = sizeof( struct sockaddr_at );
873 dst.sat_family = AF_APPLETALK;
874 dst.sat_addr.s_net = iface->i_addr.sat_addr.s_net;
875 dst.sat_addr.s_node = iface->i_addr.sat_addr.s_node;
876 memset( &loop, 0, sizeof( struct sockaddr_at ));
878 loop.sat_len = sizeof( struct sockaddr_at );
880 loop.sat_family = AF_APPLETALK;
881 loop.sat_addr.s_net = htons( ATADDR_ANYNET );
882 loop.sat_addr.s_node = ATADDR_ANYNODE;
886 (struct sockaddr *) &dst,
887 (struct sockaddr *) &loop,
888 RTF_UP | RTF_HOST ) ) {
893 (struct sockaddr_at *) &dst,
894 (struct sockaddr_at *) &loop,
895 RTF_UP | RTF_HOST ) ) {
899 if ( cmd == RTMP_ADD ) {
900 iface->i_flags |= IFACE_LOOP;
902 if ( cmd == RTMP_DEL ) {
903 iface->i_flags &= ~IFACE_LOOP;
908 int gateroute( command, rtmp )
910 struct rtmptab *rtmp;
912 struct sockaddr_at dst, gate;
915 if ( command == RTMP_DEL && ( rtmp->rt_flags & RTMPTAB_ROUTE ) == 0 ) {
918 if ( command == RTMP_ADD && ( rtmp->rt_flags & RTMPTAB_ROUTE )) {
922 net = ntohs( rtmp->rt_firstnet );
924 * Since we will accept routes from gateways who advertise their
925 * address as 0.YY, we must munge the gateway address we give to
926 * the kernel. Otherwise, we'll get a bunch of routes to the loop
927 * back interface, and who wants that?
929 memset( &gate, 0, sizeof( struct sockaddr_at ));
931 gate.sat_len = sizeof( struct sockaddr_at );
933 gate.sat_family = AF_APPLETALK;
934 gate.sat_addr.s_net = rtmp->rt_gate->g_sat.sat_addr.s_net;
935 gate.sat_addr.s_node = rtmp->rt_gate->g_sat.sat_addr.s_node;
936 if ( gate.sat_addr.s_net == 0 ) {
937 gate.sat_addr.s_net = net;
940 memset( &dst, 0, sizeof( struct sockaddr_at ));
942 dst.sat_len = sizeof( struct sockaddr_at );
944 dst.sat_family = AF_APPLETALK;
945 dst.sat_addr.s_node = ATADDR_ANYNODE;
948 dst.sat_addr.s_net = htons( net );
951 (struct sockaddr *) &dst,
952 (struct sockaddr *) &gate,
953 RTF_UP | RTF_GATEWAY )) {
954 syslog( LOG_ERR, "route: %u -> %u.%u: %m", net,
955 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
960 (struct sockaddr_at *) &dst,
961 (struct sockaddr_at *) &gate,
962 RTF_UP | RTF_GATEWAY )) {
963 syslog( LOG_ERR, "route: %u -> %u.%u: %m", net,
964 ntohs( gate.sat_addr.s_net ), gate.sat_addr.s_node );
968 } while ( net++ < ntohs( rtmp->rt_lastnet ));
970 if ( command == RTMP_ADD ) {
971 rtmp->rt_flags |= RTMPTAB_ROUTE;
973 if ( command == RTMP_DEL ) {
974 rtmp->rt_flags &= ~RTMPTAB_ROUTE;
981 newrt(const struct interface *iface)
983 struct rtmptab *rtmp;
985 if (( rtmp = (struct rtmptab *)calloc(1, sizeof(struct rtmptab))) == 0 ) {
989 rtmp->rt_iface = iface;