2 * $Id: zip.c,v 1.6 2001-06-25 20:13:45 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/param.h>
15 #include <sys/types.h>
16 #include <sys/syslog.h>
17 #include <sys/socket.h>
18 #include <sys/ioctl.h>
21 #include <net/route.h>
22 #include <netatalk/endian.h>
23 #include <netatalk/at.h>
26 #include <sys/sockio.h>
29 #include <atalk/ddp.h>
30 #include <atalk/zip.h>
31 #include <atalk/atp.h>
32 #include <atalk/util.h>
35 #include "interface.h"
40 #include "multicast.h"
43 struct ziptab *ziptab = NULL, *ziplast = NULL;
46 static int zonecheck( rtmp, iface )
48 struct interface *iface;
51 struct ziptab *czt, *zt;
54 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
58 for ( cztcnt = 0, czt = iface->i_czt; czt; czt = czt->zt_next, cztcnt++ ) {
59 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
60 zt = (struct ziptab *)l->l_data;
61 if ( czt->zt_len == zt->zt_len &&
62 !strndiacasecmp( czt->zt_name, zt->zt_name, czt->zt_len )) {
67 syslog( LOG_ERR, "zonecheck: %.*s not in zone list", czt->zt_len,
69 return( -1 ); /* configured zone not found in net zones */
73 for ( ztcnt = 0, l = rtmp->rt_zt; l; l = l->l_next, ztcnt++ )
76 if ( cztcnt != ztcnt ) {
77 syslog( LOG_ERR, "zonecheck: %d configured zones, %d zones found",
79 return( -1 ); /* more net zones than configured zones */
86 int zip_packet( ap, from, data, len )
88 struct sockaddr_at *from;
94 struct interface *iface;
99 u_short firstnet, lastnet, index, nz;
100 char *end, zname[ 32 ], packet[ ATP_BUFSIZ ], *nzones, *lastflag;
101 char *reply, *rend, *ziphdr;
102 int zlen, n, zipop, rcnt, qcnt, zcnt, zsz;
103 extern int stabletimer;
108 syslog( LOG_INFO, "zip_packet malformed packet" );
113 iface = ap->ap_iface;
117 if ( data + sizeof( struct ziphdr ) > end ) {
118 syslog( LOG_INFO, "zip_packet malformed packet" );
121 memcpy( &zh, data, sizeof( struct ziphdr ));
122 data += sizeof( struct ziphdr );
124 switch ( zh.zh_op ) {
128 rend = packet + sizeof( packet );
129 *reply++ = DDPTYPE_ZIP;
136 while ( data + sizeof( u_short ) <= end && qcnt-- > 0 ) {
137 memcpy( &firstnet, data, sizeof( u_short ));
138 data += sizeof( u_short );
141 * Look for the given network number (firstnet).
142 * Perhaps we could do better than brute force?
144 for ( iface = interfaces; iface; iface = iface->i_next ) {
145 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
146 if ( firstnet == rtmp->rt_firstnet ) {
159 * Count the number of zones in this list, and the
160 * number of byte it will consume in a reply.
162 for ( zsz = 0, zcnt = 0, l = rtmp->rt_zt; l; l = l->l_next ) {
164 zt = (struct ziptab *)l->l_data;
165 zsz += sizeof( u_short ) + 1 + zt->zt_len;
169 * We might send this list in the current reply, as the
170 * first thing in the next reply, or as an extended packet.
172 if ( reply + zsz > rend ) {
174 zh.zh_op = ZIPOP_REPLY;
176 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
177 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
178 (struct sockaddr *)from,
179 sizeof( struct sockaddr_at )) < 0 ) {
180 syslog( LOG_ERR, "zip reply sendto: %m" );
187 if ( reply + zsz > rend ) {
189 for ( l = rtmp->rt_zt; l; l = l->l_next, rcnt++ ) {
190 zt = (struct ziptab *)l->l_data;
191 if ( reply + sizeof( u_short ) + 1 + zt->zt_len >
193 zh.zh_op = ZIPOP_EREPLY;
195 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
196 if ( sendto( ap->ap_fd, packet, reply - packet,
197 0, (struct sockaddr *)from,
198 sizeof( struct sockaddr_at )) < 0 ) {
199 syslog( LOG_ERR, "zip reply sendto: %m" );
206 memcpy( reply, &firstnet, sizeof( u_short ));
207 reply += sizeof( u_short );
208 *reply++ = zt->zt_len;
209 memcpy( reply, zt->zt_name, zt->zt_len );
214 zh.zh_op = ZIPOP_EREPLY;
216 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
217 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
218 (struct sockaddr *)from,
219 sizeof( struct sockaddr_at )) < 0 ) {
220 syslog( LOG_ERR, "zip reply sendto: %m" );
230 for ( l = rtmp->rt_zt; l; l = l->l_next, rcnt++ ) {
231 zt = (struct ziptab *)l->l_data;
232 memcpy( reply, &firstnet, sizeof( u_short ));
233 reply += sizeof( u_short );
234 *reply++ = zt->zt_len;
235 memcpy( reply, zt->zt_name, zt->zt_len );
241 zh.zh_op = ZIPOP_REPLY;
243 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
244 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
245 (struct sockaddr *)from,
246 sizeof( struct sockaddr_at )) < 0 ) {
247 syslog( LOG_ERR, "zip reply sendto: %m" );
253 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
254 if (( from->sat_addr.s_net == 0 ||
255 gate->g_sat.sat_addr.s_net == from->sat_addr.s_net ) &&
256 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
260 if ( gate == NULL ) {
261 syslog( LOG_INFO, "zip reply from non-gateway %u.%u",
262 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
269 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
270 syslog( LOG_INFO, "zip reply short (%d)", len );
273 memcpy( &firstnet, data, sizeof( u_short ));
274 data += sizeof( u_short );
276 if ( rtmp && rtmp->rt_firstnet != firstnet ) {
278 if ( rtmp->rt_gate == NULL &&
279 zonecheck( rtmp, gate->g_iface ) != 0 ) {
280 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
283 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
286 /* Check if this is the interface's route. */
287 if ( firstnet == gate->g_iface->i_rt->rt_firstnet ) {
288 rtmp = gate->g_iface->i_rt;
290 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
291 if ( rtmp->rt_firstnet == firstnet ) {
297 * Update head to this rtmp entry.
299 if ( rtmp != 0 && gate->g_rt != rtmp ) {
300 gate->g_rt->rt_prev->rt_next = gate->g_rt;
302 rtmp->rt_prev->rt_next = 0;
307 if ( zlen > 32 || zlen <= 0 ) {
308 syslog( LOG_INFO, "zip reply bad packet" );
311 if ( data + zlen > end ) {
312 syslog( LOG_INFO, "zip reply short (%d)", len );
315 memcpy( zname, data, zlen );
319 * We won't find any rtmp entry if the gateway is no longer
320 * telling us about the entry.
323 syslog( LOG_INFO, "zip skip reply %u from %u.%u (no rtmp)",
324 ntohs( firstnet ), ntohs( from->sat_addr.s_net ),
325 from->sat_addr.s_node );
327 * Check if the route is still in use (the iprev check is
328 * no good if rtmp is the interface's route).
330 } else if ( rtmp->rt_iprev == NULL && rtmp->rt_prev != NULL ) {
332 "zip skip reply %u-%u from %u.%u (rtmp not in use)",
333 ntohs( rtmp->rt_firstnet ),
334 ntohs( rtmp->rt_lastnet ),
335 ntohs( from->sat_addr.s_net ),
336 from->sat_addr.s_node );
338 * Check if we've got an outstanding query for this route.
339 * We will often get this, since we ask every router on a
340 * net to verify our interface's zone(s).
342 } else if (( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) == 0 ) {
344 "zip skip reply %u-%u from %u.%u (no query)",
345 ntohs( rtmp->rt_firstnet ),
346 ntohs( rtmp->rt_lastnet ),
347 ntohs( from->sat_addr.s_net ),
348 from->sat_addr.s_node );
350 if (addzone( rtmp, zlen, zname ) < 0) {
351 syslog(LOG_ERR, "zip_packet: addzone");
354 rtmp->rt_flags |= RTMPTAB_HASZONES;
356 } while ( data < end );
358 if ( rtmp && rtmp->rt_flags & RTMPTAB_HASZONES ) {
360 if ( rtmp->rt_gate == 0 &&
361 zonecheck( rtmp, gate->g_iface ) != 0 ) {
362 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
365 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
370 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
371 if (( from->sat_addr.s_net == 0 ||
372 gate->g_sat.sat_addr.s_net == from->sat_addr.s_net ) &&
373 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
377 if ( gate == NULL ) {
378 syslog( LOG_INFO, "zip ereply from non-gateway %u.%u",
379 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
384 * Note that we're not advancing "data" here. We do that
385 * at the top of the do-while loop, below.
387 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
388 syslog( LOG_INFO, "zip ereply short (%d)", len );
391 memcpy( &firstnet, data, sizeof( u_short ));
393 /* Check if this is the interface's route. */
394 if ( firstnet == gate->g_iface->i_rt->rt_firstnet ) {
395 rtmp = gate->g_iface->i_rt;
397 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
398 if ( rtmp->rt_firstnet == firstnet ) {
402 if ( rtmp == NULL ) {
403 syslog( LOG_INFO, "zip ereply %u from %u.%u (no rtmp)",
404 ntohs( firstnet ), ntohs( from->sat_addr.s_net ),
405 from->sat_addr.s_node );
408 if ( rtmp->rt_iprev == 0 ) {
410 "zip ereply %u-%u from %u.%u (rtmp not in use)",
411 ntohs( rtmp->rt_firstnet ),
412 ntohs( rtmp->rt_lastnet ),
413 ntohs( from->sat_addr.s_net ),
414 from->sat_addr.s_node );
417 /* update head to *next* rtmp entry */
418 if ( rtmp->rt_next != 0 ) {
419 gate->g_rt->rt_prev->rt_next = gate->g_rt;
420 gate->g_rt = rtmp->rt_next;
425 if (( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) == 0 ) {
426 syslog( LOG_INFO, "zip ereply %u-%u from %u.%u (no query)",
427 ntohs( rtmp->rt_firstnet ),
428 ntohs( rtmp->rt_lastnet ),
429 ntohs( from->sat_addr.s_net ),
430 from->sat_addr.s_node );
436 * We copy out firstnet, twice (see above). Not
437 * a big deal, and it makes the end condition cleaner.
439 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
440 syslog( LOG_INFO, "zip ereply short (%d)", len );
443 memcpy( &firstnet, data, sizeof( u_short ));
444 data += sizeof( u_short );
447 if ( firstnet != rtmp->rt_firstnet ) {
448 syslog( LOG_INFO, "zip ereply with multiple nets" );
453 if ( zlen > 32 || zlen <= 0 ) {
454 syslog( LOG_INFO, "zip ereply bad zone length (%d)", zlen );
457 if ( data + zlen > end ) {
458 syslog( LOG_INFO, "zip ereply short (%d)", len );
461 memcpy( zname, data, zlen );
463 if (addzone( rtmp, zlen, zname ) < 0) {
464 syslog(LOG_ERR, "zip_packet: addzone");
467 } while ( data < end );
471 * Count zones for rtmptab entry.
473 for ( n = 0, l = rtmp->rt_zt; l; l = l->l_next, n++ )
475 if ( n == zh.zh_count ) {
476 rtmp->rt_flags |= RTMPTAB_HASZONES;
478 if ( rtmp->rt_gate == 0 &&
479 zonecheck( rtmp, gate->g_iface ) != 0 ) {
480 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
483 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
490 * Don't answer with bogus information.
492 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
493 iface->i_rt->rt_zt == 0 ||
494 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
498 if ( zh.zh_zero != 0 || data + 2 * sizeof( u_short ) > end ) {
499 syslog( LOG_INFO, "zip_packet malformed packet" );
503 memcpy( &firstnet, data, sizeof( u_short ));
504 data += sizeof( u_short );
505 memcpy( &lastnet, data, sizeof( u_short ));
506 data += sizeof( u_short );
507 if ( firstnet != 0 || lastnet != 0 || data >= end ) {
508 syslog( LOG_INFO, "zip_packet malformed packet" );
513 if ( zlen < 0 || zlen > 32 ) {
514 syslog( LOG_INFO, "zip_packet malformed packet" );
517 memcpy( zname, data, zlen );
520 end = data + sizeof( packet );
521 zh.zh_op = ZIPOP_GNIREPLY;
525 * Skip to the nets. Fill in header when we're done.
527 data += 1 + sizeof( struct ziphdr );
528 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
529 data += sizeof( u_short );
530 memcpy( data, &iface->i_rt->rt_lastnet, sizeof( u_short ));
531 data += sizeof( u_short );
534 memcpy( data, zname, zlen );
538 * Check if the given zone is valid. If it's valid, just fill in
539 * the multicast address. If it's not, fill the multicast address
540 * in with the default zone and return the default zone.
542 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
543 zt = (struct ziptab *)l->l_data;
544 if ( zt->zt_len == zlen &&
545 strndiacasecmp( zname, zt->zt_name, zlen ) == 0 ) {
550 zt = (struct ziptab *)iface->i_rt->rt_zt->l_data;
551 zh.zh_flags |= ZIPGNI_INVALID;
554 for ( n = 0, l = iface->i_rt->rt_zt; l; l = l->l_next, n++ )
557 zh.zh_flags |= ZIPGNI_ONEZONE;
561 *data++ = 6; /* sizeof ??? */
562 if (zone_bcast(zt) < 0) {
563 syslog(LOG_ERR, "zip_packet: zone_bcast");
566 memcpy(data, zt->zt_bcast, 6);
572 if ( zh.zh_flags & ZIPGNI_INVALID ) {
573 *data++ = zt->zt_len;
574 memcpy( data, zt->zt_name, zt->zt_len );
579 *packet = DDPTYPE_ZIP;
580 memcpy( packet + 1, &zh, sizeof( struct ziphdr ));
583 * If the address we received this request from isn't correct
584 * for the net we received it on, send a broadcast.
586 if ( ntohs( from->sat_addr.s_net ) <
587 ntohs( iface->i_rt->rt_firstnet ) ||
588 ntohs( from->sat_addr.s_net ) >
589 ntohs( iface->i_rt->rt_lastnet )) {
590 from->sat_addr.s_net = 0;
591 from->sat_addr.s_node = ATADDR_BCAST;
594 if ( sendto( ap->ap_fd, packet, data - packet, 0,
595 (struct sockaddr *)from,
596 sizeof( struct sockaddr_at )) < 0 ) {
597 syslog( LOG_ERR, "zip gni sendto %u.%u: %m",
598 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
603 case ZIPOP_GNIREPLY :
605 * Ignore ZIP GNIReplys which are either late or unsolicited.
607 syslog( LOG_DEBUG, "zip gnireply from %u.%u (%s %x)",
608 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
609 iface->i_name, iface->i_flags );
611 if (( iface->i_flags & ( IFACE_CONFIG|IFACE_PHASE1 )) ||
612 ( iface->i_flags & IFACE_ADDR ) == 0 ) {
613 syslog( LOG_DEBUG, "zip ignoring gnireply" );
617 if ( data + 2 * sizeof( u_short ) > end ) {
618 syslog( LOG_INFO, "zip_packet malformed packet" );
621 memcpy( &firstnet, data, sizeof( u_short ));
622 data += sizeof( u_short );
623 memcpy( &lastnet, data, sizeof( u_short ));
624 data += sizeof( u_short );
627 * We never ask for a zone, so we can get back what the
630 if ( data >= end || data + *data > end ) {
631 syslog( LOG_INFO, "zip_packet malformed packet" );
634 if ( *data++ != 0 ) {
635 syslog( LOG_INFO, "zip_packet unsolicited zone" );
639 /* skip multicast (should really check it) */
640 if ( data >= end || data + *data > end ) {
641 syslog( LOG_INFO, "zip_packet malformed packet" );
646 if ( data >= end || data + *data > end ) {
647 syslog( LOG_INFO, "zip_packet malformed packet" );
652 * First, if we're not seed, we always get our zone information
653 * from the net -- we don't even save what was in the file.
654 * Second, if we are seed, we keep our zone list in the
655 * interface structure, not in the zone table. This allows us
656 * to check that the net is giving us good zones.
658 if ( iface->i_flags & IFACE_SEED ) {
659 if ( iface->i_czt->zt_len != *data ||
660 strndiacasecmp( iface->i_czt->zt_name,
661 data + 1, *data ) != 0 ) {
662 syslog( LOG_ERR, "default zone mismatch on %s",
664 syslog( LOG_ERR, "%.*s != %.*s",
665 iface->i_czt->zt_len, iface->i_czt->zt_name,
667 syslog( LOG_ERR, "Seed error! Exiting!" );
672 if (addzone( iface->i_rt, *data, data + 1 ) < 0) {
673 syslog(LOG_ERR, "zip_packet: addzone");
678 * The netrange we received from the router doesn't match the
679 * range we have locally. This is not a problem, unless we
680 * have seed information.
682 if ( firstnet != iface->i_rt->rt_firstnet ||
683 lastnet != iface->i_rt->rt_lastnet ) {
684 if ( iface->i_flags & IFACE_SEED ) {
685 syslog( LOG_ERR, "netrange mismatch on %s",
687 syslog( LOG_ERR, "%u-%u != %u-%u",
688 ntohs( firstnet ), ntohs( lastnet ),
689 ntohs( iface->i_rt->rt_firstnet ),
690 ntohs( iface->i_rt->rt_lastnet ));
691 syslog( LOG_ERR, "Seed error! Exiting!" );
697 * It is possible that we will corrupt our route database
698 * by just forcing this change. A better solution would
699 * be to search all of our current routes, looking for
700 * this new route, and delete any old versions. Also, we
701 * would call rtmp_delete() on the old net range, in case
702 * there is some other net which actually had that range. XXX
704 iface->i_rt->rt_firstnet = firstnet;
705 iface->i_rt->rt_lastnet = lastnet;
707 if ( ntohs( iface->i_addr.sat_addr.s_net ) <
709 ntohs( iface->i_addr.sat_addr.s_net ) >
711 iface->i_addr.sat_addr.s_net = 0; /* ATADDR_ANYNET? */
713 setaddr( iface, IFACE_PHASE2, iface->i_addr.sat_addr.s_net,
714 iface->i_addr.sat_addr.s_node, firstnet, lastnet );
715 stabletimer = UNSTABLE;
718 /* add addr to loopback route */
719 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
721 "zip_packet: can't route %u.%u to loopback: %m",
722 ntohs( iface->i_addr.sat_addr.s_net ),
723 iface->i_addr.sat_addr.s_node );
727 syslog( LOG_INFO, "zip_packet configured %s from %u.%u",
728 iface->i_name, ntohs( from->sat_addr.s_net ),
729 from->sat_addr.s_node );
730 iface->i_flags |= IFACE_CONFIG;
731 if ( iface == ciface ) {
732 ciface = ciface->i_next;
739 printf( "zip notify from %u.%u\n", ntohs( from->sat_addr.s_net ),
740 from->sat_addr.s_node );
745 syslog( LOG_INFO, "zip_packet bad zip op from %u.%u\n",
746 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
751 if ( data + sizeof( struct atphdr ) > end ) {
752 syslog( LOG_INFO, "zip atp malformed packet" );
755 memcpy( &ah, data, sizeof( struct atphdr ));
756 data += sizeof( struct atphdr );
757 if ( ah.atphd_ctrlinfo != ATP_TREQ ) {
758 syslog( LOG_INFO, "zip atp bad control" );
761 ah.atphd_ctrlinfo = ATP_TRESP | ATP_EOM;
762 if ( ah.atphd_bitmap != 1 ) {
763 syslog( LOG_ERR, "zip atp bad bitmap" );
770 memcpy( &index, data, sizeof( u_short ));
771 data += sizeof( u_short );
772 index = ntohs( index );
774 syslog( LOG_INFO, "zip atp malformed packet" );
779 end = data + sizeof( packet );
780 *data++ = DDPTYPE_ATP;
781 memcpy( data, &ah, sizeof( struct atphdr ));
782 data += sizeof( struct atphdr );
783 lastflag = data++; /* mark and space for last flag */
785 nzones = data; /* mark and space for zone count */
786 data += sizeof( u_short );
789 case ZIPOP_GETMYZONE :
791 syslog( LOG_INFO, "zip atp gmz bad index" );
795 if ( iface->i_flags & IFACE_LOOPBACK ) {
796 iface = interfaces->i_next; /* first interface */
797 } else if ( ntohs( iface->i_rt->rt_firstnet ) >
798 ntohs( from->sat_addr.s_net ) ||
799 ntohs( iface->i_rt->rt_lastnet ) <
800 ntohs( from->sat_addr.s_net )) {
804 if ( iface->i_rt->rt_zt == 0 ) {
807 zt = (struct ziptab *)iface->i_rt->rt_zt->l_data;
808 if ( data + 1 + zt->zt_len > end ) {
809 syslog( LOG_INFO, "zip atp gmz reply too long" );
812 *data++ = zt->zt_len;
813 memcpy( data, zt->zt_name, zt->zt_len );
820 case ZIPOP_GETZONELIST :
821 for ( zt = ziptab; zt && ( index > 1 ); zt = zt->zt_next, index-- )
823 for ( nz = 0; zt; zt = zt->zt_next, nz++ ) {
824 if ( data + 1 + zt->zt_len > end ) {
827 *data++ = zt->zt_len;
828 memcpy( data, zt->zt_name, zt->zt_len );
832 *lastflag = ( zt == 0 ); /* Too clever? */
835 case ZIPOP_GETLOCALZONES :
836 if ( iface->i_flags & IFACE_LOOPBACK ) {
837 iface = interfaces->i_next; /* first interface */
838 } else if ( ntohs( iface->i_rt->rt_firstnet ) >
839 ntohs( from->sat_addr.s_net ) ||
840 ntohs( iface->i_rt->rt_lastnet ) <
841 ntohs( from->sat_addr.s_net )) {
845 for ( l = iface->i_rt->rt_zt; l && ( index > 1 );
846 l = l->l_next, index-- )
848 for ( nz = 0; l; l = l->l_next, nz++ ) {
849 zt = (struct ziptab *)l->l_data;
850 if ( data + 1 + zt->zt_len > end ) {
853 *data++ = zt->zt_len;
854 memcpy( data, zt->zt_name, zt->zt_len );
858 *lastflag = ( l == 0 );
862 syslog( LOG_INFO, "zip atp bad option" );
869 memcpy( nzones, &nz, sizeof( u_short ));
870 if ( sendto( ap->ap_fd, packet, data - packet, 0,
871 (struct sockaddr *)from,
872 sizeof( struct sockaddr_at )) < 0 ) {
873 syslog( LOG_ERR, "zip atp sendto %u.%u: %m",
874 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
881 syslog( LOG_INFO, "zip_packet bad ddp type from %u.%u\n",
882 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
889 int zip_getnetinfo( iface )
890 struct interface *iface;
894 struct sockaddr_at sat;
895 char *data, packet[ 40 ];
898 syslog( LOG_INFO, "zip_getnetinfo for %s", iface->i_name );
900 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
901 if ( ap->ap_packet == zip_packet ) {
906 syslog( LOG_ERR, "zip_getnetinfo can't find zip socket!" );
912 *data++ = DDPTYPE_ZIP;
914 zh.zh_op = ZIPOP_GNI;
916 memcpy( data, &zh, sizeof( struct ziphdr ));
917 data += sizeof( struct ziphdr );
919 memcpy( data, &net, sizeof( u_short ));
920 data += sizeof( u_short );
921 memcpy( data, &net, sizeof( u_short ));
922 data += sizeof( u_short );
925 * Set our requesting zone to NULL, so the response will contain
931 sat.sat_len = sizeof( struct sockaddr_at );
933 sat.sat_family = AF_APPLETALK;
934 sat.sat_addr.s_net = 0;
935 sat.sat_addr.s_node = ATADDR_BCAST;
936 sat.sat_port = ap->ap_port;
938 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
939 sizeof( struct sockaddr_at )) < 0 ) {
940 syslog( LOG_ERR, "zip_getnetinfo sendto: %m" );
953 if (( zt = (struct ziptab *)calloc(1, sizeof( struct ziptab ))) == NULL ) {
958 if (( zt->zt_name = (char *)malloc( len )) == NULL ) {
963 memcpy( zt->zt_name, name, len );
969 * Insert at the end. Return 1 if a mapping already exists, 0 otherwise.
972 static int add_list( head, data )
978 for ( l = *head; l; l = l->l_next ) {
979 if ( l->l_data == data ) {
983 if (( l = (struct list *)malloc( sizeof( struct list ))) == NULL ) {
984 syslog( LOG_ERR, "add_list malloc: %m" );
990 if ( *head == NULL ) {
994 /* find end of list */
995 for ( l2 = *head; l2->l_next; l2 = l2->l_next )
1003 int addzone( rt, len, zone )
1011 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1012 if ( zt->zt_len == len &&
1013 strndiacasecmp( zt->zt_name, zone, len ) == 0 ) {
1018 if (( zt = newzt( len, zone )) == NULL ) {
1019 syslog( LOG_ERR, "addzone newzt: %m" );
1022 if ( ziptab == NULL ) {
1026 zt->zt_prev = ziplast;
1027 ziplast->zt_next = zt;
1032 if ((cc = add_list( &zt->zt_rt, rt )) < 0)
1038 if ((cc = add_list( &rt->rt_zt, zt )) < 0 )
1043 syslog( LOG_ERR, "addzone corrupted route/zone mapping" );
1047 * We get the repeat for local nets which have zone information
1048 * already: we ask anyway, just to make sure.
1054 syslog( LOG_ERR, "addzone corrupted zone/route mapping" );