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"
41 struct ziptab *ziptab = NULL, *ziplast = NULL;
44 static int zonecheck( rtmp, iface )
46 struct interface *iface;
49 struct ziptab *czt, *zt;
52 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
56 for ( cztcnt = 0, czt = iface->i_czt; czt; czt = czt->zt_next, cztcnt++ ) {
57 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
58 zt = (struct ziptab *)l->l_data;
59 if ( czt->zt_len == zt->zt_len &&
60 !strndiacasecmp( czt->zt_name, zt->zt_name, czt->zt_len )) {
65 syslog( LOG_ERR, "zonecheck: %.*s not in zone list", czt->zt_len,
67 return( -1 ); /* configured zone not found in net zones */
71 for ( ztcnt = 0, l = rtmp->rt_zt; l; l = l->l_next, ztcnt++ )
74 if ( cztcnt != ztcnt ) {
75 syslog( LOG_ERR, "zonecheck: %d configured zones, %d zones found",
77 return( -1 ); /* more net zones than configured zones */
84 int zip_packet( ap, from, data, len )
86 struct sockaddr_at *from;
92 struct interface *iface;
97 u_short firstnet, lastnet, index, nz;
98 char *end, zname[ 32 ], packet[ ATP_BUFSIZ ], *nzones, *lastflag;
99 char *reply, *rend, *ziphdr;
100 int zlen, n, zipop, rcnt, qcnt, zcnt, zsz;
101 extern int debug, stabletimer;
106 syslog( LOG_INFO, "zip_packet malformed packet" );
111 iface = ap->ap_iface;
115 if ( data + sizeof( struct ziphdr ) > end ) {
116 syslog( LOG_INFO, "zip_packet malformed packet" );
119 memcpy( &zh, data, sizeof( struct ziphdr ));
120 data += sizeof( struct ziphdr );
122 switch ( zh.zh_op ) {
126 rend = packet + sizeof( packet );
127 *reply++ = DDPTYPE_ZIP;
134 while ( data + sizeof( u_short ) <= end && qcnt-- > 0 ) {
135 memcpy( &firstnet, data, sizeof( u_short ));
136 data += sizeof( u_short );
139 * Look for the given network number (firstnet).
140 * Perhaps we could do better than brute force?
142 for ( iface = interfaces; iface; iface = iface->i_next ) {
143 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
144 if ( firstnet == rtmp->rt_firstnet ) {
157 * Count the number of zones in this list, and the
158 * number of byte it will consume in a reply.
160 for ( zsz = 0, zcnt = 0, l = rtmp->rt_zt; l; l = l->l_next ) {
162 zt = (struct ziptab *)l->l_data;
163 zsz += sizeof( u_short ) + 1 + zt->zt_len;
167 * We might send this list in the current reply, as the
168 * first thing in the next reply, or as an extended packet.
170 if ( reply + zsz > rend ) {
172 zh.zh_op = ZIPOP_REPLY;
174 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
175 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
176 (struct sockaddr *)from,
177 sizeof( struct sockaddr_at )) < 0 ) {
178 syslog( LOG_ERR, "zip reply sendto: %m" );
185 if ( reply + zsz > rend ) {
187 for ( l = rtmp->rt_zt; l; l = l->l_next, rcnt++ ) {
188 zt = (struct ziptab *)l->l_data;
189 if ( reply + sizeof( u_short ) + 1 + zt->zt_len >
191 zh.zh_op = ZIPOP_EREPLY;
193 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
194 if ( sendto( ap->ap_fd, packet, reply - packet,
195 0, (struct sockaddr *)from,
196 sizeof( struct sockaddr_at )) < 0 ) {
197 syslog( LOG_ERR, "zip reply sendto: %m" );
204 memcpy( reply, &firstnet, sizeof( u_short ));
205 reply += sizeof( u_short );
206 *reply++ = zt->zt_len;
207 memcpy( reply, zt->zt_name, zt->zt_len );
212 zh.zh_op = ZIPOP_EREPLY;
214 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
215 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
216 (struct sockaddr *)from,
217 sizeof( struct sockaddr_at )) < 0 ) {
218 syslog( LOG_ERR, "zip reply sendto: %m" );
228 for ( l = rtmp->rt_zt; l; l = l->l_next, rcnt++ ) {
229 zt = (struct ziptab *)l->l_data;
230 memcpy( reply, &firstnet, sizeof( u_short ));
231 reply += sizeof( u_short );
232 *reply++ = zt->zt_len;
233 memcpy( reply, zt->zt_name, zt->zt_len );
239 zh.zh_op = ZIPOP_REPLY;
241 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
242 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
243 (struct sockaddr *)from,
244 sizeof( struct sockaddr_at )) < 0 ) {
245 syslog( LOG_ERR, "zip reply sendto: %m" );
251 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
252 if (( from->sat_addr.s_net == 0 ||
253 gate->g_sat.sat_addr.s_net == from->sat_addr.s_net ) &&
254 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
258 if ( gate == NULL ) {
259 syslog( LOG_INFO, "zip reply from non-gateway %u.%u",
260 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
267 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
268 syslog( LOG_INFO, "zip reply short (%d)", len );
271 memcpy( &firstnet, data, sizeof( u_short ));
272 data += sizeof( u_short );
274 if ( rtmp && rtmp->rt_firstnet != firstnet ) {
276 if ( rtmp->rt_gate == NULL &&
277 zonecheck( rtmp, gate->g_iface ) != 0 ) {
278 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
281 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
284 /* Check if this is the interface's route. */
285 if ( firstnet == gate->g_iface->i_rt->rt_firstnet ) {
286 rtmp = gate->g_iface->i_rt;
288 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
289 if ( rtmp->rt_firstnet == firstnet ) {
295 * Update head to this rtmp entry.
297 if ( rtmp != 0 && gate->g_rt != rtmp ) {
298 gate->g_rt->rt_prev->rt_next = gate->g_rt;
300 rtmp->rt_prev->rt_next = 0;
305 if ( zlen > 32 || zlen <= 0 ) {
306 syslog( LOG_INFO, "zip reply bad packet" );
309 if ( data + zlen > end ) {
310 syslog( LOG_INFO, "zip reply short (%d)", len );
313 memcpy( zname, data, zlen );
317 * We won't find any rtmp entry if the gateway is no longer
318 * telling us about the entry.
321 syslog( LOG_INFO, "zip skip reply %u from %u.%u (no rtmp)",
322 ntohs( firstnet ), ntohs( from->sat_addr.s_net ),
323 from->sat_addr.s_node );
325 * Check if the route is still in use (the iprev check is
326 * no good if rtmp is the interface's route).
328 } else if ( rtmp->rt_iprev == NULL && rtmp->rt_prev != NULL ) {
330 "zip skip reply %u-%u from %u.%u (rtmp not in use)",
331 ntohs( rtmp->rt_firstnet ),
332 ntohs( rtmp->rt_lastnet ),
333 ntohs( from->sat_addr.s_net ),
334 from->sat_addr.s_node );
336 * Check if we've got an outstanding query for this route.
337 * We will often get this, since we ask every router on a
338 * net to verify our interface's zone(s).
340 } else if (( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) == 0 ) {
342 "zip skip reply %u-%u from %u.%u (no query)",
343 ntohs( rtmp->rt_firstnet ),
344 ntohs( rtmp->rt_lastnet ),
345 ntohs( from->sat_addr.s_net ),
346 from->sat_addr.s_node );
348 if (addzone( rtmp, zlen, zname ) < 0) {
349 syslog(LOG_ERR, "zip_packet: addzone");
352 rtmp->rt_flags |= RTMPTAB_HASZONES;
354 } while ( data < end );
356 if ( rtmp && rtmp->rt_flags & RTMPTAB_HASZONES ) {
358 if ( rtmp->rt_gate == 0 &&
359 zonecheck( rtmp, gate->g_iface ) != 0 ) {
360 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
363 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
368 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
369 if (( from->sat_addr.s_net == 0 ||
370 gate->g_sat.sat_addr.s_net == from->sat_addr.s_net ) &&
371 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
375 if ( gate == NULL ) {
376 syslog( LOG_INFO, "zip ereply from non-gateway %u.%u",
377 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
382 * Note that we're not advancing "data" here. We do that
383 * at the top of the do-while loop, below.
385 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
386 syslog( LOG_INFO, "zip ereply short (%d)", len );
389 memcpy( &firstnet, data, sizeof( u_short ));
391 /* Check if this is the interface's route. */
392 if ( firstnet == gate->g_iface->i_rt->rt_firstnet ) {
393 rtmp = gate->g_iface->i_rt;
395 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
396 if ( rtmp->rt_firstnet == firstnet ) {
400 if ( rtmp == NULL ) {
401 syslog( LOG_INFO, "zip ereply %u from %u.%u (no rtmp)",
402 ntohs( firstnet ), ntohs( from->sat_addr.s_net ),
403 from->sat_addr.s_node );
406 if ( rtmp->rt_iprev == 0 ) {
408 "zip ereply %u-%u from %u.%u (rtmp not in use)",
409 ntohs( rtmp->rt_firstnet ),
410 ntohs( rtmp->rt_lastnet ),
411 ntohs( from->sat_addr.s_net ),
412 from->sat_addr.s_node );
415 /* update head to *next* rtmp entry */
416 if ( rtmp->rt_next != 0 ) {
417 gate->g_rt->rt_prev->rt_next = gate->g_rt;
418 gate->g_rt = rtmp->rt_next;
423 if (( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) == 0 ) {
424 syslog( LOG_INFO, "zip ereply %u-%u from %u.%u (no query)",
425 ntohs( rtmp->rt_firstnet ),
426 ntohs( rtmp->rt_lastnet ),
427 ntohs( from->sat_addr.s_net ),
428 from->sat_addr.s_node );
434 * We copy out firstnet, twice (see above). Not
435 * a big deal, and it makes the end condition cleaner.
437 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
438 syslog( LOG_INFO, "zip ereply short (%d)", len );
441 memcpy( &firstnet, data, sizeof( u_short ));
442 data += sizeof( u_short );
445 if ( firstnet != rtmp->rt_firstnet ) {
446 syslog( LOG_INFO, "zip ereply with multiple nets" );
451 if ( zlen > 32 || zlen <= 0 ) {
452 syslog( LOG_INFO, "zip ereply bad zone length (%d)", zlen );
455 if ( data + zlen > end ) {
456 syslog( LOG_INFO, "zip ereply short (%d)", len );
459 memcpy( zname, data, zlen );
461 if (addzone( rtmp, zlen, zname ) < 0) {
462 syslog(LOG_ERR, "zip_packet: addzone");
465 } while ( data < end );
469 * Count zones for rtmptab entry.
471 for ( n = 0, l = rtmp->rt_zt; l; l = l->l_next, n++ )
473 if ( n == zh.zh_count ) {
474 rtmp->rt_flags |= RTMPTAB_HASZONES;
476 if ( rtmp->rt_gate == 0 &&
477 zonecheck( rtmp, gate->g_iface ) != 0 ) {
478 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
481 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
488 * Don't answer with bogus information.
490 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
491 iface->i_rt->rt_zt == 0 ||
492 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
496 if ( zh.zh_zero != 0 || data + 2 * sizeof( u_short ) > end ) {
497 syslog( LOG_INFO, "zip_packet malformed packet" );
501 memcpy( &firstnet, data, sizeof( u_short ));
502 data += sizeof( u_short );
503 memcpy( &lastnet, data, sizeof( u_short ));
504 data += sizeof( u_short );
505 if ( firstnet != 0 || lastnet != 0 || data >= end ) {
506 syslog( LOG_INFO, "zip_packet malformed packet" );
511 if ( zlen < 0 || zlen > 32 ) {
512 syslog( LOG_INFO, "zip_packet malformed packet" );
515 memcpy( zname, data, zlen );
518 end = data + sizeof( packet );
519 zh.zh_op = ZIPOP_GNIREPLY;
523 * Skip to the nets. Fill in header when we're done.
525 data += 1 + sizeof( struct ziphdr );
526 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
527 data += sizeof( u_short );
528 memcpy( data, &iface->i_rt->rt_lastnet, sizeof( u_short ));
529 data += sizeof( u_short );
532 memcpy( data, zname, zlen );
536 * Check if the given zone is valid. If it's valid, just fill in
537 * the multicast address. If it's not, fill the multicast address
538 * in with the default zone and return the default zone.
540 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
541 zt = (struct ziptab *)l->l_data;
542 if ( zt->zt_len == zlen &&
543 strndiacasecmp( zname, zt->zt_name, zlen ) == 0 ) {
548 zt = (struct ziptab *)iface->i_rt->rt_zt->l_data;
549 zh.zh_flags |= ZIPGNI_INVALID;
552 for ( n = 0, l = iface->i_rt->rt_zt; l; l = l->l_next, n++ )
555 zh.zh_flags |= ZIPGNI_ONEZONE;
559 *data++ = 6; /* sizeof ??? */
560 if (zone_bcast(zt) < 0) {
561 syslog(LOG_ERR, "zip_packet: zone_bcast");
564 memcpy(data, zt->zt_bcast, 6);
570 if ( zh.zh_flags & ZIPGNI_INVALID ) {
571 *data++ = zt->zt_len;
572 memcpy( data, zt->zt_name, zt->zt_len );
577 *packet = DDPTYPE_ZIP;
578 memcpy( packet + 1, &zh, sizeof( struct ziphdr ));
581 * If the address we received this request from isn't correct
582 * for the net we received it on, send a broadcast.
584 if ( ntohs( from->sat_addr.s_net ) <
585 ntohs( iface->i_rt->rt_firstnet ) ||
586 ntohs( from->sat_addr.s_net ) >
587 ntohs( iface->i_rt->rt_lastnet )) {
588 from->sat_addr.s_net = 0;
589 from->sat_addr.s_node = ATADDR_BCAST;
592 if ( sendto( ap->ap_fd, packet, data - packet, 0,
593 (struct sockaddr *)from,
594 sizeof( struct sockaddr_at )) < 0 ) {
595 syslog( LOG_ERR, "zip gni sendto %u.%u: %m",
596 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
601 case ZIPOP_GNIREPLY :
603 * Ignore ZIP GNIReplys which are either late or unsolicited.
605 syslog( LOG_DEBUG, "zip gnireply from %u.%u (%s %x)",
606 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
607 iface->i_name, iface->i_flags );
609 if (( iface->i_flags & ( IFACE_CONFIG|IFACE_PHASE1 )) ||
610 ( iface->i_flags & IFACE_ADDR ) == 0 ) {
611 syslog( LOG_DEBUG, "zip ignoring gnireply" );
615 if ( data + 2 * sizeof( u_short ) > end ) {
616 syslog( LOG_INFO, "zip_packet malformed packet" );
619 memcpy( &firstnet, data, sizeof( u_short ));
620 data += sizeof( u_short );
621 memcpy( &lastnet, data, sizeof( u_short ));
622 data += sizeof( u_short );
625 * We never ask for a zone, so we can get back what the
628 if ( data >= end || data + *data > end ) {
629 syslog( LOG_INFO, "zip_packet malformed packet" );
632 if ( *data++ != 0 ) {
633 syslog( LOG_INFO, "zip_packet unsolicited zone" );
637 /* skip multicast (should really check it) */
638 if ( data >= end || data + *data > end ) {
639 syslog( LOG_INFO, "zip_packet malformed packet" );
644 if ( data >= end || data + *data > end ) {
645 syslog( LOG_INFO, "zip_packet malformed packet" );
650 * First, if we're not seed, we always get our zone information
651 * from the net -- we don't even save what was in the file.
652 * Second, if we are seed, we keep our zone list in the
653 * interface structure, not in the zone table. This allows us
654 * to check that the net is giving us good zones.
656 if ( iface->i_flags & IFACE_SEED ) {
657 if ( iface->i_czt->zt_len != *data ||
658 strndiacasecmp( iface->i_czt->zt_name,
659 data + 1, *data ) != 0 ) {
660 syslog( LOG_ERR, "default zone mismatch on %s",
662 syslog( LOG_ERR, "%.*s != %.*s",
663 iface->i_czt->zt_len, iface->i_czt->zt_name,
665 syslog( LOG_ERR, "Seed error! Exiting!" );
670 if (addzone( iface->i_rt, *data, data + 1 ) < 0) {
671 syslog(LOG_ERR, "zip_packet: addzone");
676 * The netrange we received from the router doesn't match the
677 * range we have locally. This is not a problem, unless we
678 * have seed information.
680 if ( firstnet != iface->i_rt->rt_firstnet ||
681 lastnet != iface->i_rt->rt_lastnet ) {
682 if ( iface->i_flags & IFACE_SEED ) {
683 syslog( LOG_ERR, "netrange mismatch on %s",
685 syslog( LOG_ERR, "%u-%u != %u-%u",
686 ntohs( firstnet ), ntohs( lastnet ),
687 ntohs( iface->i_rt->rt_firstnet ),
688 ntohs( iface->i_rt->rt_lastnet ));
689 syslog( LOG_ERR, "Seed error! Exiting!" );
695 * It is possible that we will corrupt our route database
696 * by just forcing this change. A better solution would
697 * be to search all of our current routes, looking for
698 * this new route, and delete any old versions. Also, we
699 * would call rtmp_delete() on the old net range, in case
700 * there is some other net which actually had that range. XXX
702 iface->i_rt->rt_firstnet = firstnet;
703 iface->i_rt->rt_lastnet = lastnet;
705 if ( ntohs( iface->i_addr.sat_addr.s_net ) <
707 ntohs( iface->i_addr.sat_addr.s_net ) >
709 iface->i_addr.sat_addr.s_net = 0; /* ATADDR_ANYNET? */
711 setaddr( iface, IFACE_PHASE2, iface->i_addr.sat_addr.s_net,
712 iface->i_addr.sat_addr.s_node, firstnet, lastnet );
713 stabletimer = UNSTABLE;
716 /* add addr to loopback route */
717 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
719 "zip_packet: can't route %u.%u to loopback: %m",
720 ntohs( iface->i_addr.sat_addr.s_net ),
721 iface->i_addr.sat_addr.s_node );
725 syslog( LOG_INFO, "zip_packet configured %s from %u.%u",
726 iface->i_name, ntohs( from->sat_addr.s_net ),
727 from->sat_addr.s_node );
728 iface->i_flags |= IFACE_CONFIG;
729 if ( iface == ciface ) {
730 ciface = ciface->i_next;
737 printf( "zip notify from %u.%u\n", ntohs( from->sat_addr.s_net ),
738 from->sat_addr.s_node );
743 syslog( LOG_INFO, "zip_packet bad zip op from %u.%u\n",
744 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
749 if ( data + sizeof( struct atphdr ) > end ) {
750 syslog( LOG_INFO, "zip atp malformed packet" );
753 memcpy( &ah, data, sizeof( struct atphdr ));
754 data += sizeof( struct atphdr );
755 if ( ah.atphd_ctrlinfo != ATP_TREQ ) {
756 syslog( LOG_INFO, "zip atp bad control" );
759 ah.atphd_ctrlinfo = ATP_TRESP | ATP_EOM;
760 if ( ah.atphd_bitmap != 1 ) {
761 syslog( LOG_ERR, "zip atp bad bitmap" );
768 memcpy( &index, data, sizeof( u_short ));
769 data += sizeof( u_short );
770 index = ntohs( index );
772 syslog( LOG_INFO, "zip atp malformed packet" );
777 end = data + sizeof( packet );
778 *data++ = DDPTYPE_ATP;
779 memcpy( data, &ah, sizeof( struct atphdr ));
780 data += sizeof( struct atphdr );
781 lastflag = data++; /* mark and space for last flag */
783 nzones = data; /* mark and space for zone count */
784 data += sizeof( u_short );
787 case ZIPOP_GETMYZONE :
789 syslog( LOG_INFO, "zip atp gmz bad index" );
793 if ( iface->i_flags & IFACE_LOOPBACK ) {
794 iface = interfaces->i_next; /* first interface */
795 } else if ( ntohs( iface->i_rt->rt_firstnet ) >
796 ntohs( from->sat_addr.s_net ) ||
797 ntohs( iface->i_rt->rt_lastnet ) <
798 ntohs( from->sat_addr.s_net )) {
802 if ( iface->i_rt->rt_zt == 0 ) {
805 zt = (struct ziptab *)iface->i_rt->rt_zt->l_data;
806 if ( data + 1 + zt->zt_len > end ) {
807 syslog( LOG_INFO, "zip atp gmz reply too long" );
810 *data++ = zt->zt_len;
811 memcpy( data, zt->zt_name, zt->zt_len );
818 case ZIPOP_GETZONELIST :
819 for ( zt = ziptab; zt && ( index > 1 ); zt = zt->zt_next, index-- )
821 for ( nz = 0; zt; zt = zt->zt_next, nz++ ) {
822 if ( data + 1 + zt->zt_len > end ) {
825 *data++ = zt->zt_len;
826 memcpy( data, zt->zt_name, zt->zt_len );
830 *lastflag = ( zt == 0 ); /* Too clever? */
833 case ZIPOP_GETLOCALZONES :
834 if ( iface->i_flags & IFACE_LOOPBACK ) {
835 iface = interfaces->i_next; /* first interface */
836 } else if ( ntohs( iface->i_rt->rt_firstnet ) >
837 ntohs( from->sat_addr.s_net ) ||
838 ntohs( iface->i_rt->rt_lastnet ) <
839 ntohs( from->sat_addr.s_net )) {
843 for ( l = iface->i_rt->rt_zt; l && ( index > 1 );
844 l = l->l_next, index-- )
846 for ( nz = 0; l; l = l->l_next, nz++ ) {
847 zt = (struct ziptab *)l->l_data;
848 if ( data + 1 + zt->zt_len > end ) {
851 *data++ = zt->zt_len;
852 memcpy( data, zt->zt_name, zt->zt_len );
856 *lastflag = ( l == 0 );
860 syslog( LOG_INFO, "zip atp bad option" );
867 memcpy( nzones, &nz, sizeof( u_short ));
868 if ( sendto( ap->ap_fd, packet, data - packet, 0,
869 (struct sockaddr *)from,
870 sizeof( struct sockaddr_at )) < 0 ) {
871 syslog( LOG_ERR, "zip atp sendto %u.%u: %m",
872 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
879 syslog( LOG_INFO, "zip_packet bad ddp type from %u.%u\n",
880 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
887 int zip_getnetinfo( iface )
888 struct interface *iface;
892 struct sockaddr_at sat;
893 char *data, packet[ 40 ];
896 syslog( LOG_INFO, "zip_getnetinfo for %s", iface->i_name );
898 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
899 if ( ap->ap_packet == zip_packet ) {
904 syslog( LOG_ERR, "zip_getnetinfo can't find zip socket!" );
910 *data++ = DDPTYPE_ZIP;
912 zh.zh_op = ZIPOP_GNI;
914 memcpy( data, &zh, sizeof( struct ziphdr ));
915 data += sizeof( struct ziphdr );
917 memcpy( data, &net, sizeof( u_short ));
918 data += sizeof( u_short );
919 memcpy( data, &net, sizeof( u_short ));
920 data += sizeof( u_short );
923 * Set our requesting zone to NULL, so the response will contain
929 sat.sat_len = sizeof( struct sockaddr_at );
931 sat.sat_family = AF_APPLETALK;
932 sat.sat_addr.s_net = 0;
933 sat.sat_addr.s_node = ATADDR_BCAST;
934 sat.sat_port = ap->ap_port;
936 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
937 sizeof( struct sockaddr_at )) < 0 ) {
938 syslog( LOG_ERR, "zip_getnetinfo sendto: %m" );
951 if (( zt = (struct ziptab *)calloc(1, sizeof( struct ziptab ))) == NULL ) {
956 if (( zt->zt_name = (char *)malloc( len )) == NULL ) {
961 memcpy( zt->zt_name, name, len );
967 * Insert at the end. Return 1 if a mapping already exists, 0 otherwise.
970 static int add_list( head, data )
976 for ( l = *head; l; l = l->l_next ) {
977 if ( l->l_data == data ) {
981 if (( l = (struct list *)malloc( sizeof( struct list ))) == NULL ) {
982 syslog( LOG_ERR, "add_list malloc: %m" );
988 if ( *head == NULL ) {
992 /* find end of list */
993 for ( l2 = *head; l2->l_next; l2 = l2->l_next )
1001 int addzone( rt, len, zone )
1009 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1010 if ( zt->zt_len == len &&
1011 strndiacasecmp( zt->zt_name, zone, len ) == 0 ) {
1016 if (( zt = newzt( len, zone )) == NULL ) {
1017 syslog( LOG_ERR, "addzone newzt: %m" );
1020 if ( ziptab == NULL ) {
1024 zt->zt_prev = ziplast;
1025 ziplast->zt_next = zt;
1030 if ((cc = add_list( &zt->zt_rt, rt )) < 0)
1036 if ((cc = add_list( &rt->rt_zt, zt )) < 0 )
1041 syslog( LOG_ERR, "addzone corrupted route/zone mapping" );
1045 * We get the repeat for local nets which have zone information
1046 * already: we ask anyway, just to make sure.
1052 syslog( LOG_ERR, "addzone corrupted zone/route mapping" );