2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
12 #include <sys/param.h>
13 #include <sys/types.h>
14 #include <sys/syslog.h>
15 #include <sys/socket.h>
16 #include <sys/ioctl.h>
19 #include <net/route.h>
20 #include <netatalk/endian.h>
21 #include <netatalk/at.h>
24 #include <sys/sockio.h>
27 #include <atalk/ddp.h>
28 #include <atalk/zip.h>
29 #include <atalk/atp.h>
30 #include <atalk/util.h>
33 #include "interface.h"
38 #include "multicast.h"
40 struct ziptab *ziptab = NULL, *ziplast = NULL;
42 static int zonecheck( rtmp, iface )
44 struct interface *iface;
47 struct ziptab *czt, *zt;
50 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
54 for ( cztcnt = 0, czt = iface->i_czt; czt; czt = czt->zt_next, cztcnt++ ) {
55 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
56 zt = (struct ziptab *)l->l_data;
57 if ( czt->zt_len == zt->zt_len &&
58 !strndiacasecmp( czt->zt_name, zt->zt_name, czt->zt_len )) {
63 syslog( LOG_ERR, "zonecheck: %.*s not in zone list", czt->zt_len,
65 return( -1 ); /* configured zone not found in net zones */
69 for ( ztcnt = 0, l = rtmp->rt_zt; l; l = l->l_next, ztcnt++ )
72 if ( cztcnt != ztcnt ) {
73 syslog( LOG_ERR, "zonecheck: %d configured zones, %d zones found",
75 return( -1 ); /* more net zones than configured zones */
82 int zip_packet( ap, from, data, len )
84 struct sockaddr_at *from;
90 struct interface *iface;
95 u_short firstnet, lastnet, index, nz;
96 char *end, zname[ 32 ], packet[ ATP_BUFSIZ ], *nzones, *lastflag;
97 char *reply, *rend, *ziphdr;
98 int zlen, n, zipop, rcnt, qcnt, zcnt, zsz;
99 extern int debug, stabletimer;
104 syslog( LOG_INFO, "zip_packet malformed packet" );
109 iface = ap->ap_iface;
113 if ( data + sizeof( struct ziphdr ) > end ) {
114 syslog( LOG_INFO, "zip_packet malformed packet" );
117 memcpy( &zh, data, sizeof( struct ziphdr ));
118 data += sizeof( struct ziphdr );
120 switch ( zh.zh_op ) {
124 rend = packet + sizeof( packet );
125 *reply++ = DDPTYPE_ZIP;
132 while ( data + sizeof( u_short ) <= end && qcnt-- > 0 ) {
133 memcpy( &firstnet, data, sizeof( u_short ));
134 data += sizeof( u_short );
137 * Look for the given network number (firstnet).
138 * Perhaps we could do better than brute force?
140 for ( iface = interfaces; iface; iface = iface->i_next ) {
141 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
142 if ( firstnet == rtmp->rt_firstnet ) {
155 * Count the number of zones in this list, and the
156 * number of byte it will consume in a reply.
158 for ( zsz = 0, zcnt = 0, l = rtmp->rt_zt; l; l = l->l_next ) {
160 zt = (struct ziptab *)l->l_data;
161 zsz += sizeof( u_short ) + 1 + zt->zt_len;
165 * We might send this list in the current reply, as the
166 * first thing in the next reply, or as an extended packet.
168 if ( reply + zsz > rend ) {
170 zh.zh_op = ZIPOP_REPLY;
172 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
173 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
174 (struct sockaddr *)from,
175 sizeof( struct sockaddr_at )) < 0 ) {
176 syslog( LOG_ERR, "zip reply sendto: %m" );
183 if ( reply + zsz > rend ) {
185 for ( l = rtmp->rt_zt; l; l = l->l_next, rcnt++ ) {
186 zt = (struct ziptab *)l->l_data;
187 if ( reply + sizeof( u_short ) + 1 + zt->zt_len >
189 zh.zh_op = ZIPOP_EREPLY;
191 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
192 if ( sendto( ap->ap_fd, packet, reply - packet,
193 0, (struct sockaddr *)from,
194 sizeof( struct sockaddr_at )) < 0 ) {
195 syslog( LOG_ERR, "zip reply sendto: %m" );
202 memcpy( reply, &firstnet, sizeof( u_short ));
203 reply += sizeof( u_short );
204 *reply++ = zt->zt_len;
205 memcpy( reply, zt->zt_name, zt->zt_len );
210 zh.zh_op = ZIPOP_EREPLY;
212 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
213 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
214 (struct sockaddr *)from,
215 sizeof( struct sockaddr_at )) < 0 ) {
216 syslog( LOG_ERR, "zip reply sendto: %m" );
226 for ( l = rtmp->rt_zt; l; l = l->l_next, rcnt++ ) {
227 zt = (struct ziptab *)l->l_data;
228 memcpy( reply, &firstnet, sizeof( u_short ));
229 reply += sizeof( u_short );
230 *reply++ = zt->zt_len;
231 memcpy( reply, zt->zt_name, zt->zt_len );
237 zh.zh_op = ZIPOP_REPLY;
239 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
240 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
241 (struct sockaddr *)from,
242 sizeof( struct sockaddr_at )) < 0 ) {
243 syslog( LOG_ERR, "zip reply sendto: %m" );
249 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
250 if (( from->sat_addr.s_net == 0 ||
251 gate->g_sat.sat_addr.s_net == from->sat_addr.s_net ) &&
252 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
256 if ( gate == NULL ) {
257 syslog( LOG_INFO, "zip reply from non-gateway %u.%u",
258 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
265 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
266 syslog( LOG_INFO, "zip reply short (%d)", len );
269 memcpy( &firstnet, data, sizeof( u_short ));
270 data += sizeof( u_short );
272 if ( rtmp && rtmp->rt_firstnet != firstnet ) {
274 if ( rtmp->rt_gate == NULL &&
275 zonecheck( rtmp, gate->g_iface ) != 0 ) {
276 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
279 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
282 /* Check if this is the interface's route. */
283 if ( firstnet == gate->g_iface->i_rt->rt_firstnet ) {
284 rtmp = gate->g_iface->i_rt;
286 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
287 if ( rtmp->rt_firstnet == firstnet ) {
293 * Update head to this rtmp entry.
295 if ( rtmp != 0 && gate->g_rt != rtmp ) {
296 gate->g_rt->rt_prev->rt_next = gate->g_rt;
298 rtmp->rt_prev->rt_next = 0;
303 if ( zlen > 32 || zlen <= 0 ) {
304 syslog( LOG_INFO, "zip reply bad packet" );
307 if ( data + zlen > end ) {
308 syslog( LOG_INFO, "zip reply short (%d)", len );
311 memcpy( zname, data, zlen );
315 * We won't find any rtmp entry if the gateway is no longer
316 * telling us about the entry.
319 syslog( LOG_INFO, "zip skip reply %u from %u.%u (no rtmp)",
320 ntohs( firstnet ), ntohs( from->sat_addr.s_net ),
321 from->sat_addr.s_node );
323 * Check if the route is still in use (the iprev check is
324 * no good if rtmp is the interface's route).
326 } else if ( rtmp->rt_iprev == NULL && rtmp->rt_prev != NULL ) {
328 "zip skip reply %u-%u from %u.%u (rtmp not in use)",
329 ntohs( rtmp->rt_firstnet ),
330 ntohs( rtmp->rt_lastnet ),
331 ntohs( from->sat_addr.s_net ),
332 from->sat_addr.s_node );
334 * Check if we've got an outstanding query for this route.
335 * We will often get this, since we ask every router on a
336 * net to verify our interface's zone(s).
338 } else if (( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) == 0 ) {
340 "zip skip reply %u-%u from %u.%u (no query)",
341 ntohs( rtmp->rt_firstnet ),
342 ntohs( rtmp->rt_lastnet ),
343 ntohs( from->sat_addr.s_net ),
344 from->sat_addr.s_node );
346 if (addzone( rtmp, zlen, zname ) < 0) {
347 syslog(LOG_ERR, "zip_packet: addzone");
350 rtmp->rt_flags |= RTMPTAB_HASZONES;
352 } while ( data < end );
354 if ( rtmp && rtmp->rt_flags & RTMPTAB_HASZONES ) {
356 if ( rtmp->rt_gate == 0 &&
357 zonecheck( rtmp, gate->g_iface ) != 0 ) {
358 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
361 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
366 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
367 if (( from->sat_addr.s_net == 0 ||
368 gate->g_sat.sat_addr.s_net == from->sat_addr.s_net ) &&
369 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
373 if ( gate == NULL ) {
374 syslog( LOG_INFO, "zip ereply from non-gateway %u.%u",
375 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
380 * Note that we're not advancing "data" here. We do that
381 * at the top of the do-while loop, below.
383 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
384 syslog( LOG_INFO, "zip ereply short (%d)", len );
387 memcpy( &firstnet, data, sizeof( u_short ));
389 /* Check if this is the interface's route. */
390 if ( firstnet == gate->g_iface->i_rt->rt_firstnet ) {
391 rtmp = gate->g_iface->i_rt;
393 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
394 if ( rtmp->rt_firstnet == firstnet ) {
398 if ( rtmp == NULL ) {
399 syslog( LOG_INFO, "zip ereply %u from %u.%u (no rtmp)",
400 ntohs( firstnet ), ntohs( from->sat_addr.s_net ),
401 from->sat_addr.s_node );
404 if ( rtmp->rt_iprev == 0 ) {
406 "zip ereply %u-%u from %u.%u (rtmp not in use)",
407 ntohs( rtmp->rt_firstnet ),
408 ntohs( rtmp->rt_lastnet ),
409 ntohs( from->sat_addr.s_net ),
410 from->sat_addr.s_node );
413 /* update head to *next* rtmp entry */
414 if ( rtmp->rt_next != 0 ) {
415 gate->g_rt->rt_prev->rt_next = gate->g_rt;
416 gate->g_rt = rtmp->rt_next;
421 if (( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) == 0 ) {
422 syslog( LOG_INFO, "zip ereply %u-%u from %u.%u (no query)",
423 ntohs( rtmp->rt_firstnet ),
424 ntohs( rtmp->rt_lastnet ),
425 ntohs( from->sat_addr.s_net ),
426 from->sat_addr.s_node );
432 * We copy out firstnet, twice (see above). Not
433 * a big deal, and it makes the end condition cleaner.
435 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
436 syslog( LOG_INFO, "zip ereply short (%d)", len );
439 memcpy( &firstnet, data, sizeof( u_short ));
440 data += sizeof( u_short );
443 if ( firstnet != rtmp->rt_firstnet ) {
444 syslog( LOG_INFO, "zip ereply with multiple nets" );
449 if ( zlen > 32 || zlen <= 0 ) {
450 syslog( LOG_INFO, "zip ereply bad zone length (%d)", zlen );
453 if ( data + zlen > end ) {
454 syslog( LOG_INFO, "zip ereply short (%d)", len );
457 memcpy( zname, data, zlen );
459 if (addzone( rtmp, zlen, zname ) < 0) {
460 syslog(LOG_ERR, "zip_packet: addzone");
463 } while ( data < end );
467 * Count zones for rtmptab entry.
469 for ( n = 0, l = rtmp->rt_zt; l; l = l->l_next, n++ )
471 if ( n == zh.zh_count ) {
472 rtmp->rt_flags |= RTMPTAB_HASZONES;
474 if ( rtmp->rt_gate == 0 &&
475 zonecheck( rtmp, gate->g_iface ) != 0 ) {
476 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
479 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
486 * Don't answer with bogus information.
488 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
489 iface->i_rt->rt_zt == 0 ||
490 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
494 if ( zh.zh_zero != 0 || data + 2 * sizeof( u_short ) > end ) {
495 syslog( LOG_INFO, "zip_packet malformed packet" );
499 memcpy( &firstnet, data, sizeof( u_short ));
500 data += sizeof( u_short );
501 memcpy( &lastnet, data, sizeof( u_short ));
502 data += sizeof( u_short );
503 if ( firstnet != 0 || lastnet != 0 || data >= end ) {
504 syslog( LOG_INFO, "zip_packet malformed packet" );
509 if ( zlen < 0 || zlen > 32 ) {
510 syslog( LOG_INFO, "zip_packet malformed packet" );
513 memcpy( zname, data, zlen );
516 end = data + sizeof( packet );
517 zh.zh_op = ZIPOP_GNIREPLY;
521 * Skip to the nets. Fill in header when we're done.
523 data += 1 + sizeof( struct ziphdr );
524 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
525 data += sizeof( u_short );
526 memcpy( data, &iface->i_rt->rt_lastnet, sizeof( u_short ));
527 data += sizeof( u_short );
530 memcpy( data, zname, zlen );
534 * Check if the given zone is valid. If it's valid, just fill in
535 * the multicast address. If it's not, fill the multicast address
536 * in with the default zone and return the default zone.
538 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
539 zt = (struct ziptab *)l->l_data;
540 if ( zt->zt_len == zlen &&
541 strndiacasecmp( zname, zt->zt_name, zlen ) == 0 ) {
546 zt = (struct ziptab *)iface->i_rt->rt_zt->l_data;
547 zh.zh_flags |= ZIPGNI_INVALID;
550 for ( n = 0, l = iface->i_rt->rt_zt; l; l = l->l_next, n++ )
553 zh.zh_flags |= ZIPGNI_ONEZONE;
557 *data++ = 6; /* sizeof ??? */
558 if (zone_bcast(zt) < 0) {
559 syslog(LOG_ERR, "zip_packet: zone_bcast");
562 memcpy(data, zt->zt_bcast, 6);
568 if ( zh.zh_flags & ZIPGNI_INVALID ) {
569 *data++ = zt->zt_len;
570 memcpy( data, zt->zt_name, zt->zt_len );
575 *packet = DDPTYPE_ZIP;
576 memcpy( packet + 1, &zh, sizeof( struct ziphdr ));
579 * If the address we received this request from isn't correct
580 * for the net we received it on, send a broadcast.
582 if ( ntohs( from->sat_addr.s_net ) <
583 ntohs( iface->i_rt->rt_firstnet ) ||
584 ntohs( from->sat_addr.s_net ) >
585 ntohs( iface->i_rt->rt_lastnet )) {
586 from->sat_addr.s_net = 0;
587 from->sat_addr.s_node = ATADDR_BCAST;
590 if ( sendto( ap->ap_fd, packet, data - packet, 0,
591 (struct sockaddr *)from,
592 sizeof( struct sockaddr_at )) < 0 ) {
593 syslog( LOG_ERR, "zip gni sendto %u.%u: %m",
594 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
599 case ZIPOP_GNIREPLY :
601 * Ignore ZIP GNIReplys which are either late or unsolicited.
603 syslog( LOG_DEBUG, "zip gnireply from %u.%u (%s %x)",
604 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
605 iface->i_name, iface->i_flags );
607 if (( iface->i_flags & ( IFACE_CONFIG|IFACE_PHASE1 )) ||
608 ( iface->i_flags & IFACE_ADDR ) == 0 ) {
609 syslog( LOG_DEBUG, "zip ignoring gnireply" );
613 if ( data + 2 * sizeof( u_short ) > end ) {
614 syslog( LOG_INFO, "zip_packet malformed packet" );
617 memcpy( &firstnet, data, sizeof( u_short ));
618 data += sizeof( u_short );
619 memcpy( &lastnet, data, sizeof( u_short ));
620 data += sizeof( u_short );
623 * We never ask for a zone, so we can get back what the
626 if ( data >= end || data + *data > end ) {
627 syslog( LOG_INFO, "zip_packet malformed packet" );
630 if ( *data++ != 0 ) {
631 syslog( LOG_INFO, "zip_packet unsolicited zone" );
635 /* skip multicast (should really check it) */
636 if ( data >= end || data + *data > end ) {
637 syslog( LOG_INFO, "zip_packet malformed packet" );
642 if ( data >= end || data + *data > end ) {
643 syslog( LOG_INFO, "zip_packet malformed packet" );
648 * First, if we're not seed, we always get our zone information
649 * from the net -- we don't even save what was in the file.
650 * Second, if we are seed, we keep our zone list in the
651 * interface structure, not in the zone table. This allows us
652 * to check that the net is giving us good zones.
654 if ( iface->i_flags & IFACE_SEED ) {
655 if ( iface->i_czt->zt_len != *data ||
656 strndiacasecmp( iface->i_czt->zt_name,
657 data + 1, *data ) != 0 ) {
658 syslog( LOG_ERR, "default zone mismatch on %s",
660 syslog( LOG_ERR, "%.*s != %.*s",
661 iface->i_czt->zt_len, iface->i_czt->zt_name,
663 syslog( LOG_ERR, "Seed error! Exiting!" );
668 if (addzone( iface->i_rt, *data, data + 1 ) < 0) {
669 syslog(LOG_ERR, "zip_packet: addzone");
674 * The netrange we received from the router doesn't match the
675 * range we have locally. This is not a problem, unless we
676 * have seed information.
678 if ( firstnet != iface->i_rt->rt_firstnet ||
679 lastnet != iface->i_rt->rt_lastnet ) {
680 if ( iface->i_flags & IFACE_SEED ) {
681 syslog( LOG_ERR, "netrange mismatch on %s",
683 syslog( LOG_ERR, "%u-%u != %u-%u",
684 ntohs( firstnet ), ntohs( lastnet ),
685 ntohs( iface->i_rt->rt_firstnet ),
686 ntohs( iface->i_rt->rt_lastnet ));
687 syslog( LOG_ERR, "Seed error! Exiting!" );
693 * It is possible that we will corrupt our route database
694 * by just forcing this change. A better solution would
695 * be to search all of our current routes, looking for
696 * this new route, and delete any old versions. Also, we
697 * would call rtmp_delete() on the old net range, in case
698 * there is some other net which actually had that range. XXX
700 iface->i_rt->rt_firstnet = firstnet;
701 iface->i_rt->rt_lastnet = lastnet;
703 if ( ntohs( iface->i_addr.sat_addr.s_net ) <
705 ntohs( iface->i_addr.sat_addr.s_net ) >
707 iface->i_addr.sat_addr.s_net = 0; /* ATADDR_ANYNET? */
709 setaddr( iface, IFACE_PHASE2, iface->i_addr.sat_addr.s_net,
710 iface->i_addr.sat_addr.s_node, firstnet, lastnet );
711 stabletimer = UNSTABLE;
714 /* add addr to loopback route */
715 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
717 "zip_packet: can't route %u.%u to loopback: %m",
718 ntohs( iface->i_addr.sat_addr.s_net ),
719 iface->i_addr.sat_addr.s_node );
723 syslog( LOG_INFO, "zip_packet configured %s from %u.%u",
724 iface->i_name, ntohs( from->sat_addr.s_net ),
725 from->sat_addr.s_node );
726 iface->i_flags |= IFACE_CONFIG;
727 if ( iface == ciface ) {
728 ciface = ciface->i_next;
735 printf( "zip notify from %u.%u\n", ntohs( from->sat_addr.s_net ),
736 from->sat_addr.s_node );
741 syslog( LOG_INFO, "zip_packet bad zip op from %u.%u\n",
742 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
747 if ( data + sizeof( struct atphdr ) > end ) {
748 syslog( LOG_INFO, "zip atp malformed packet" );
751 memcpy( &ah, data, sizeof( struct atphdr ));
752 data += sizeof( struct atphdr );
753 if ( ah.atphd_ctrlinfo != ATP_TREQ ) {
754 syslog( LOG_INFO, "zip atp bad control" );
757 ah.atphd_ctrlinfo = ATP_TRESP | ATP_EOM;
758 if ( ah.atphd_bitmap != 1 ) {
759 syslog( LOG_ERR, "zip atp bad bitmap" );
766 memcpy( &index, data, sizeof( u_short ));
767 data += sizeof( u_short );
768 index = ntohs( index );
770 syslog( LOG_INFO, "zip atp malformed packet" );
775 end = data + sizeof( packet );
776 *data++ = DDPTYPE_ATP;
777 memcpy( data, &ah, sizeof( struct atphdr ));
778 data += sizeof( struct atphdr );
779 lastflag = data++; /* mark and space for last flag */
781 nzones = data; /* mark and space for zone count */
782 data += sizeof( u_short );
785 case ZIPOP_GETMYZONE :
787 syslog( LOG_INFO, "zip atp gmz bad index" );
791 if ( iface->i_flags & IFACE_LOOPBACK ) {
792 iface = interfaces->i_next; /* first interface */
793 } else if ( ntohs( iface->i_rt->rt_firstnet ) >
794 ntohs( from->sat_addr.s_net ) ||
795 ntohs( iface->i_rt->rt_lastnet ) <
796 ntohs( from->sat_addr.s_net )) {
800 if ( iface->i_rt->rt_zt == 0 ) {
803 zt = (struct ziptab *)iface->i_rt->rt_zt->l_data;
804 if ( data + 1 + zt->zt_len > end ) {
805 syslog( LOG_INFO, "zip atp gmz reply too long" );
808 *data++ = zt->zt_len;
809 memcpy( data, zt->zt_name, zt->zt_len );
816 case ZIPOP_GETZONELIST :
817 for ( zt = ziptab; zt && ( index > 1 ); zt = zt->zt_next, index-- )
819 for ( nz = 0; zt; zt = zt->zt_next, nz++ ) {
820 if ( data + 1 + zt->zt_len > end ) {
823 *data++ = zt->zt_len;
824 memcpy( data, zt->zt_name, zt->zt_len );
828 *lastflag = ( zt == 0 ); /* Too clever? */
831 case ZIPOP_GETLOCALZONES :
832 if ( iface->i_flags & IFACE_LOOPBACK ) {
833 iface = interfaces->i_next; /* first interface */
834 } else if ( ntohs( iface->i_rt->rt_firstnet ) >
835 ntohs( from->sat_addr.s_net ) ||
836 ntohs( iface->i_rt->rt_lastnet ) <
837 ntohs( from->sat_addr.s_net )) {
841 for ( l = iface->i_rt->rt_zt; l && ( index > 1 );
842 l = l->l_next, index-- )
844 for ( nz = 0; l; l = l->l_next, nz++ ) {
845 zt = (struct ziptab *)l->l_data;
846 if ( data + 1 + zt->zt_len > end ) {
849 *data++ = zt->zt_len;
850 memcpy( data, zt->zt_name, zt->zt_len );
854 *lastflag = ( l == 0 );
858 syslog( LOG_INFO, "zip atp bad option" );
865 memcpy( nzones, &nz, sizeof( u_short ));
866 if ( sendto( ap->ap_fd, packet, data - packet, 0,
867 (struct sockaddr *)from,
868 sizeof( struct sockaddr_at )) < 0 ) {
869 syslog( LOG_ERR, "zip atp sendto %u.%u: %m",
870 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
877 syslog( LOG_INFO, "zip_packet bad ddp type from %u.%u\n",
878 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
885 int zip_getnetinfo( iface )
886 struct interface *iface;
890 struct sockaddr_at sat;
891 char *data, packet[ 40 ];
894 syslog( LOG_INFO, "zip_getnetinfo for %s", iface->i_name );
896 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
897 if ( ap->ap_packet == zip_packet ) {
902 syslog( LOG_ERR, "zip_getnetinfo can't find zip socket!" );
908 *data++ = DDPTYPE_ZIP;
910 zh.zh_op = ZIPOP_GNI;
912 memcpy( data, &zh, sizeof( struct ziphdr ));
913 data += sizeof( struct ziphdr );
915 memcpy( data, &net, sizeof( u_short ));
916 data += sizeof( u_short );
917 memcpy( data, &net, sizeof( u_short ));
918 data += sizeof( u_short );
921 * Set our requesting zone to NULL, so the response will contain
927 sat.sat_len = sizeof( struct sockaddr_at );
929 sat.sat_family = AF_APPLETALK;
930 sat.sat_addr.s_net = 0;
931 sat.sat_addr.s_node = ATADDR_BCAST;
932 sat.sat_port = ap->ap_port;
934 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
935 sizeof( struct sockaddr_at )) < 0 ) {
936 syslog( LOG_ERR, "zip_getnetinfo sendto: %m" );
949 if (( zt = (struct ziptab *)calloc(1, sizeof( struct ziptab ))) == NULL ) {
954 if (( zt->zt_name = (char *)malloc( len )) == NULL ) {
959 memcpy( zt->zt_name, name, len );
965 * Insert at the end. Return 1 if a mapping already exists, 0 otherwise.
968 static int add_list( head, data )
974 for ( l = *head; l; l = l->l_next ) {
975 if ( l->l_data == data ) {
979 if (( l = (struct list *)malloc( sizeof( struct list ))) == NULL ) {
980 syslog( LOG_ERR, "add_list malloc: %m" );
986 if ( *head == NULL ) {
990 /* find end of list */
991 for ( l2 = *head; l2->l_next; l2 = l2->l_next )
999 int addzone( rt, len, zone )
1007 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1008 if ( zt->zt_len == len &&
1009 strndiacasecmp( zt->zt_name, zone, len ) == 0 ) {
1014 if (( zt = newzt( len, zone )) == NULL ) {
1015 syslog( LOG_ERR, "addzone newzt: %m" );
1018 if ( ziptab == NULL ) {
1022 zt->zt_prev = ziplast;
1023 ziplast->zt_next = zt;
1028 if ((cc = add_list( &zt->zt_rt, rt )) < 0)
1034 if ((cc = add_list( &rt->rt_zt, zt )) < 0 )
1039 syslog( LOG_ERR, "addzone corrupted route/zone mapping" );
1043 * We get the repeat for local nets which have zone information
1044 * already: we ask anyway, just to make sure.
1050 syslog( LOG_ERR, "addzone corrupted zone/route mapping" );