2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
10 #include <sys/syslog.h>
11 #include <sys/socket.h>
12 #include <sys/ioctl.h>
15 #include <net/route.h>
16 #include <netatalk/endian.h>
17 #include <netatalk/at.h>
20 #include <sys/sockio.h>
23 #include <atalk/ddp.h>
24 #include <atalk/zip.h>
25 #include <atalk/atp.h>
26 #include <atalk/util.h>
29 #include "interface.h"
34 #include "multicast.h"
36 struct ziptab *ziptab = NULL, *ziplast = NULL;
38 static int zonecheck( rtmp, iface )
40 struct interface *iface;
43 struct ziptab *czt, *zt;
46 if (( iface->i_flags & IFACE_SEED ) == 0 ) {
50 for ( cztcnt = 0, czt = iface->i_czt; czt; czt = czt->zt_next, cztcnt++ ) {
51 for ( l = rtmp->rt_zt; l; l = l->l_next ) {
52 zt = (struct ziptab *)l->l_data;
53 if ( czt->zt_len == zt->zt_len &&
54 !strndiacasecmp( czt->zt_name, zt->zt_name, czt->zt_len )) {
59 syslog( LOG_ERR, "zonecheck: %.*s not in zone list", czt->zt_len,
61 return( -1 ); /* configured zone not found in net zones */
65 for ( ztcnt = 0, l = rtmp->rt_zt; l; l = l->l_next, ztcnt++ )
68 if ( cztcnt != ztcnt ) {
69 syslog( LOG_ERR, "zonecheck: %d configured zones, %d zones found",
71 return( -1 ); /* more net zones than configured zones */
78 int zip_packet( ap, from, data, len )
80 struct sockaddr_at *from;
86 struct interface *iface;
91 u_short firstnet, lastnet, index, nz;
92 char *end, zname[ 32 ], packet[ ATP_BUFSIZ ], *nzones, *lastflag;
93 char *reply, *rend, *ziphdr;
94 int zlen, n, zipop, rcnt, qcnt, zcnt, zsz;
95 extern int debug, stabletimer;
100 syslog( LOG_INFO, "zip_packet malformed packet" );
105 iface = ap->ap_iface;
109 if ( data + sizeof( struct ziphdr ) > end ) {
110 syslog( LOG_INFO, "zip_packet malformed packet" );
113 memcpy( &zh, data, sizeof( struct ziphdr ));
114 data += sizeof( struct ziphdr );
116 switch ( zh.zh_op ) {
120 rend = packet + sizeof( packet );
121 *reply++ = DDPTYPE_ZIP;
128 while ( data + sizeof( u_short ) <= end && qcnt-- > 0 ) {
129 memcpy( &firstnet, data, sizeof( u_short ));
130 data += sizeof( u_short );
133 * Look for the given network number (firstnet).
134 * Perhaps we could do better than brute force?
136 for ( iface = interfaces; iface; iface = iface->i_next ) {
137 for ( rtmp = iface->i_rt; rtmp; rtmp = rtmp->rt_inext ) {
138 if ( firstnet == rtmp->rt_firstnet ) {
151 * Count the number of zones in this list, and the
152 * number of byte it will consume in a reply.
154 for ( zsz = 0, zcnt = 0, l = rtmp->rt_zt; l; l = l->l_next ) {
156 zt = (struct ziptab *)l->l_data;
157 zsz += sizeof( u_short ) + 1 + zt->zt_len;
161 * We might send this list in the current reply, as the
162 * first thing in the next reply, or as an extended packet.
164 if ( reply + zsz > rend ) {
166 zh.zh_op = ZIPOP_REPLY;
168 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
169 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
170 (struct sockaddr *)from,
171 sizeof( struct sockaddr_at )) < 0 ) {
172 syslog( LOG_ERR, "zip reply sendto: %m" );
179 if ( reply + zsz > rend ) {
181 for ( l = rtmp->rt_zt; l; l = l->l_next, rcnt++ ) {
182 zt = (struct ziptab *)l->l_data;
183 if ( reply + sizeof( u_short ) + 1 + zt->zt_len >
185 zh.zh_op = ZIPOP_EREPLY;
187 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
188 if ( sendto( ap->ap_fd, packet, reply - packet,
189 0, (struct sockaddr *)from,
190 sizeof( struct sockaddr_at )) < 0 ) {
191 syslog( LOG_ERR, "zip reply sendto: %m" );
198 memcpy( reply, &firstnet, sizeof( u_short ));
199 reply += sizeof( u_short );
200 *reply++ = zt->zt_len;
201 memcpy( reply, zt->zt_name, zt->zt_len );
206 zh.zh_op = ZIPOP_EREPLY;
208 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
209 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
210 (struct sockaddr *)from,
211 sizeof( struct sockaddr_at )) < 0 ) {
212 syslog( LOG_ERR, "zip reply sendto: %m" );
222 for ( l = rtmp->rt_zt; l; l = l->l_next, rcnt++ ) {
223 zt = (struct ziptab *)l->l_data;
224 memcpy( reply, &firstnet, sizeof( u_short ));
225 reply += sizeof( u_short );
226 *reply++ = zt->zt_len;
227 memcpy( reply, zt->zt_name, zt->zt_len );
233 zh.zh_op = ZIPOP_REPLY;
235 memcpy( ziphdr, &zh, sizeof( struct ziphdr ));
236 if ( sendto( ap->ap_fd, packet, reply - packet, 0,
237 (struct sockaddr *)from,
238 sizeof( struct sockaddr_at )) < 0 ) {
239 syslog( LOG_ERR, "zip reply sendto: %m" );
245 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
246 if (( from->sat_addr.s_net == 0 ||
247 gate->g_sat.sat_addr.s_net == from->sat_addr.s_net ) &&
248 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
252 if ( gate == NULL ) {
253 syslog( LOG_INFO, "zip reply from non-gateway %u.%u",
254 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
261 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
262 syslog( LOG_INFO, "zip reply short (%d)", len );
265 memcpy( &firstnet, data, sizeof( u_short ));
266 data += sizeof( u_short );
268 if ( rtmp && rtmp->rt_firstnet != firstnet ) {
270 if ( rtmp->rt_gate == NULL &&
271 zonecheck( rtmp, gate->g_iface ) != 0 ) {
272 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
275 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
278 /* Check if this is the interface's route. */
279 if ( firstnet == gate->g_iface->i_rt->rt_firstnet ) {
280 rtmp = gate->g_iface->i_rt;
282 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
283 if ( rtmp->rt_firstnet == firstnet ) {
289 * Update head to this rtmp entry.
291 if ( rtmp != 0 && gate->g_rt != rtmp ) {
292 gate->g_rt->rt_prev->rt_next = gate->g_rt;
294 rtmp->rt_prev->rt_next = 0;
299 if ( zlen > 32 || zlen <= 0 ) {
300 syslog( LOG_INFO, "zip reply bad packet" );
303 if ( data + zlen > end ) {
304 syslog( LOG_INFO, "zip reply short (%d)", len );
307 memcpy( zname, data, zlen );
311 * We won't find any rtmp entry if the gateway is no longer
312 * telling us about the entry.
315 syslog( LOG_INFO, "zip skip reply %u from %u.%u (no rtmp)",
316 ntohs( firstnet ), ntohs( from->sat_addr.s_net ),
317 from->sat_addr.s_node );
319 * Check if the route is still in use (the iprev check is
320 * no good if rtmp is the interface's route).
322 } else if ( rtmp->rt_iprev == NULL && rtmp->rt_prev != NULL ) {
324 "zip skip reply %u-%u from %u.%u (rtmp not in use)",
325 ntohs( rtmp->rt_firstnet ),
326 ntohs( rtmp->rt_lastnet ),
327 ntohs( from->sat_addr.s_net ),
328 from->sat_addr.s_node );
330 * Check if we've got an outstanding query for this route.
331 * We will often get this, since we ask every router on a
332 * net to verify our interface's zone(s).
334 } else if (( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) == 0 ) {
336 "zip skip reply %u-%u from %u.%u (no query)",
337 ntohs( rtmp->rt_firstnet ),
338 ntohs( rtmp->rt_lastnet ),
339 ntohs( from->sat_addr.s_net ),
340 from->sat_addr.s_node );
342 if (addzone( rtmp, zlen, zname ) < 0) {
343 syslog(LOG_ERR, "zip_packet: addzone");
346 rtmp->rt_flags |= RTMPTAB_HASZONES;
348 } while ( data < end );
350 if ( rtmp && rtmp->rt_flags & RTMPTAB_HASZONES ) {
352 if ( rtmp->rt_gate == 0 &&
353 zonecheck( rtmp, gate->g_iface ) != 0 ) {
354 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
357 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
362 for ( gate = iface->i_gate; gate; gate = gate->g_next ) {
363 if (( from->sat_addr.s_net == 0 ||
364 gate->g_sat.sat_addr.s_net == from->sat_addr.s_net ) &&
365 gate->g_sat.sat_addr.s_node == from->sat_addr.s_node ) {
369 if ( gate == NULL ) {
370 syslog( LOG_INFO, "zip ereply from non-gateway %u.%u",
371 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
376 * Note that we're not advancing "data" here. We do that
377 * at the top of the do-while loop, below.
379 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
380 syslog( LOG_INFO, "zip ereply short (%d)", len );
383 memcpy( &firstnet, data, sizeof( u_short ));
385 /* Check if this is the interface's route. */
386 if ( firstnet == gate->g_iface->i_rt->rt_firstnet ) {
387 rtmp = gate->g_iface->i_rt;
389 for ( rtmp = gate->g_rt; rtmp; rtmp = rtmp->rt_next ) {
390 if ( rtmp->rt_firstnet == firstnet ) {
394 if ( rtmp == NULL ) {
395 syslog( LOG_INFO, "zip ereply %u from %u.%u (no rtmp)",
396 ntohs( firstnet ), ntohs( from->sat_addr.s_net ),
397 from->sat_addr.s_node );
400 if ( rtmp->rt_iprev == 0 ) {
402 "zip ereply %u-%u from %u.%u (rtmp not in use)",
403 ntohs( rtmp->rt_firstnet ),
404 ntohs( rtmp->rt_lastnet ),
405 ntohs( from->sat_addr.s_net ),
406 from->sat_addr.s_node );
409 /* update head to *next* rtmp entry */
410 if ( rtmp->rt_next != 0 ) {
411 gate->g_rt->rt_prev->rt_next = gate->g_rt;
412 gate->g_rt = rtmp->rt_next;
417 if (( rtmp->rt_flags & RTMPTAB_ZIPQUERY ) == 0 ) {
418 syslog( LOG_INFO, "zip ereply %u-%u from %u.%u (no query)",
419 ntohs( rtmp->rt_firstnet ),
420 ntohs( rtmp->rt_lastnet ),
421 ntohs( from->sat_addr.s_net ),
422 from->sat_addr.s_node );
428 * We copy out firstnet, twice (see above). Not
429 * a big deal, and it makes the end condition cleaner.
431 if ( data + sizeof( u_short ) + 1 > end ) { /* + strlen */
432 syslog( LOG_INFO, "zip ereply short (%d)", len );
435 memcpy( &firstnet, data, sizeof( u_short ));
436 data += sizeof( u_short );
439 if ( firstnet != rtmp->rt_firstnet ) {
440 syslog( LOG_INFO, "zip ereply with multiple nets" );
445 if ( zlen > 32 || zlen <= 0 ) {
446 syslog( LOG_INFO, "zip ereply bad zone length (%d)", zlen );
449 if ( data + zlen > end ) {
450 syslog( LOG_INFO, "zip ereply short (%d)", len );
453 memcpy( zname, data, zlen );
455 if (addzone( rtmp, zlen, zname ) < 0) {
456 syslog(LOG_ERR, "zip_packet: addzone");
459 } while ( data < end );
463 * Count zones for rtmptab entry.
465 for ( n = 0, l = rtmp->rt_zt; l; l = l->l_next, n++ )
467 if ( n == zh.zh_count ) {
468 rtmp->rt_flags |= RTMPTAB_HASZONES;
470 if ( rtmp->rt_gate == 0 &&
471 zonecheck( rtmp, gate->g_iface ) != 0 ) {
472 syslog( LOG_ERR, "zip_packet seed zonelist mismatch" );
475 rtmp->rt_flags &= ~RTMPTAB_ZIPQUERY;
482 * Don't answer with bogus information.
484 if (((iface->i_flags & IFACE_ISROUTER) == 0) ||
485 iface->i_rt->rt_zt == 0 ||
486 ( iface->i_flags & IFACE_CONFIG ) == 0 ) {
490 if ( zh.zh_zero != 0 || data + 2 * sizeof( u_short ) > end ) {
491 syslog( LOG_INFO, "zip_packet malformed packet" );
495 memcpy( &firstnet, data, sizeof( u_short ));
496 data += sizeof( u_short );
497 memcpy( &lastnet, data, sizeof( u_short ));
498 data += sizeof( u_short );
499 if ( firstnet != 0 || lastnet != 0 || data >= end ) {
500 syslog( LOG_INFO, "zip_packet malformed packet" );
505 if ( zlen < 0 || zlen > 32 ) {
506 syslog( LOG_INFO, "zip_packet malformed packet" );
509 memcpy( zname, data, zlen );
512 end = data + sizeof( packet );
513 zh.zh_op = ZIPOP_GNIREPLY;
517 * Skip to the nets. Fill in header when we're done.
519 data += 1 + sizeof( struct ziphdr );
520 memcpy( data, &iface->i_rt->rt_firstnet, sizeof( u_short ));
521 data += sizeof( u_short );
522 memcpy( data, &iface->i_rt->rt_lastnet, sizeof( u_short ));
523 data += sizeof( u_short );
526 memcpy( data, zname, zlen );
530 * Check if the given zone is valid. If it's valid, just fill in
531 * the multicast address. If it's not, fill the multicast address
532 * in with the default zone and return the default zone.
534 for ( l = iface->i_rt->rt_zt; l; l = l->l_next ) {
535 zt = (struct ziptab *)l->l_data;
536 if ( zt->zt_len == zlen &&
537 strndiacasecmp( zname, zt->zt_name, zlen ) == 0 ) {
542 zt = (struct ziptab *)iface->i_rt->rt_zt->l_data;
543 zh.zh_flags |= ZIPGNI_INVALID;
546 for ( n = 0, l = iface->i_rt->rt_zt; l; l = l->l_next, n++ )
549 zh.zh_flags |= ZIPGNI_ONEZONE;
553 *data++ = 6; /* sizeof ??? */
554 if (zone_bcast(zt) < 0) {
555 syslog(LOG_ERR, "zip_packet: zone_bcast");
558 memcpy(data, zt->zt_bcast, 6);
564 if ( zh.zh_flags & ZIPGNI_INVALID ) {
565 *data++ = zt->zt_len;
566 memcpy( data, zt->zt_name, zt->zt_len );
571 *packet = DDPTYPE_ZIP;
572 memcpy( packet + 1, &zh, sizeof( struct ziphdr ));
575 * If the address we received this request from isn't correct
576 * for the net we received it on, send a broadcast.
578 if ( ntohs( from->sat_addr.s_net ) <
579 ntohs( iface->i_rt->rt_firstnet ) ||
580 ntohs( from->sat_addr.s_net ) >
581 ntohs( iface->i_rt->rt_lastnet )) {
582 from->sat_addr.s_net = 0;
583 from->sat_addr.s_node = ATADDR_BCAST;
586 if ( sendto( ap->ap_fd, packet, data - packet, 0,
587 (struct sockaddr *)from,
588 sizeof( struct sockaddr_at )) < 0 ) {
589 syslog( LOG_ERR, "zip gni sendto %u.%u: %m",
590 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
595 case ZIPOP_GNIREPLY :
597 * Ignore ZIP GNIReplys which are either late or unsolicited.
599 syslog( LOG_INFO, "zip gnireply from %u.%u (%s %x)",
600 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node,
601 iface->i_name, iface->i_flags );
603 if (( iface->i_flags & ( IFACE_CONFIG|IFACE_PHASE1 )) ||
604 ( iface->i_flags & IFACE_ADDR ) == 0 ) {
605 syslog( LOG_INFO, "zip ignoring gnireply" );
609 if ( data + 2 * sizeof( u_short ) > end ) {
610 syslog( LOG_INFO, "zip_packet malformed packet" );
613 memcpy( &firstnet, data, sizeof( u_short ));
614 data += sizeof( u_short );
615 memcpy( &lastnet, data, sizeof( u_short ));
616 data += sizeof( u_short );
619 * We never ask for a zone, so we can get back what the
622 if ( data >= end || data + *data > end ) {
623 syslog( LOG_INFO, "zip_packet malformed packet" );
626 if ( *data++ != 0 ) {
627 syslog( LOG_INFO, "zip_packet unsolicited zone" );
631 /* skip multicast (should really check it) */
632 if ( data >= end || data + *data > end ) {
633 syslog( LOG_INFO, "zip_packet malformed packet" );
638 if ( data >= end || data + *data > end ) {
639 syslog( LOG_INFO, "zip_packet malformed packet" );
644 * First, if we're not seed, we always get our zone information
645 * from the net -- we don't even save what was in the file.
646 * Second, if we are seed, we keep our zone list in the
647 * interface structure, not in the zone table. This allows us
648 * to check that the net is giving us good zones.
650 if ( iface->i_flags & IFACE_SEED ) {
651 if ( iface->i_czt->zt_len != *data ||
652 strndiacasecmp( iface->i_czt->zt_name,
653 data + 1, *data ) != 0 ) {
654 syslog( LOG_ERR, "default zone mismatch on %s",
656 syslog( LOG_ERR, "%.*s != %.*s",
657 iface->i_czt->zt_len, iface->i_czt->zt_name,
659 syslog( LOG_ERR, "Seed error! Exiting!" );
664 if (addzone( iface->i_rt, *data, data + 1 ) < 0) {
665 syslog(LOG_ERR, "zip_packet: addzone");
670 * The netrange we received from the router doesn't match the
671 * range we have locally. This is not a problem, unless we
672 * have seed information.
674 if ( firstnet != iface->i_rt->rt_firstnet ||
675 lastnet != iface->i_rt->rt_lastnet ) {
676 if ( iface->i_flags & IFACE_SEED ) {
677 syslog( LOG_ERR, "netrange mismatch on %s",
679 syslog( LOG_ERR, "%u-%u != %u-%u",
680 ntohs( firstnet ), ntohs( lastnet ),
681 ntohs( iface->i_rt->rt_firstnet ),
682 ntohs( iface->i_rt->rt_lastnet ));
683 syslog( LOG_ERR, "Seed error! Exiting!" );
689 * It is possible that we will corrupt our route database
690 * by just forcing this change. A better solution would
691 * be to search all of our current routes, looking for
692 * this new route, and delete any old versions. Also, we
693 * would call rtmp_delete() on the old net range, in case
694 * there is some other net which actually had that range. XXX
696 iface->i_rt->rt_firstnet = firstnet;
697 iface->i_rt->rt_lastnet = lastnet;
699 if ( ntohs( iface->i_addr.sat_addr.s_net ) <
701 ntohs( iface->i_addr.sat_addr.s_net ) >
703 iface->i_addr.sat_addr.s_net = 0; /* ATADDR_ANYNET? */
705 setaddr( iface, IFACE_PHASE2, iface->i_addr.sat_addr.s_net,
706 iface->i_addr.sat_addr.s_node, firstnet, lastnet );
707 stabletimer = UNSTABLE;
710 /* add addr to loopback route */
711 if ( looproute( iface, RTMP_ADD )) { /* -1 or 1 */
713 "zip_packet: can't route %u.%u to loopback: %m",
714 ntohs( iface->i_addr.sat_addr.s_net ),
715 iface->i_addr.sat_addr.s_node );
719 syslog( LOG_INFO, "zip_packet configured %s from %u.%u",
720 iface->i_name, ntohs( from->sat_addr.s_net ),
721 from->sat_addr.s_node );
722 iface->i_flags |= IFACE_CONFIG;
723 if ( iface == ciface ) {
724 ciface = ciface->i_next;
731 printf( "zip notify from %u.%u\n", ntohs( from->sat_addr.s_net ),
732 from->sat_addr.s_node );
737 syslog( LOG_INFO, "zip_packet bad zip op from %u.%u\n",
738 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
743 if ( data + sizeof( struct atphdr ) > end ) {
744 syslog( LOG_INFO, "zip atp malformed packet" );
747 memcpy( &ah, data, sizeof( struct atphdr ));
748 data += sizeof( struct atphdr );
749 if ( ah.atphd_ctrlinfo != ATP_TREQ ) {
750 syslog( LOG_INFO, "zip atp bad control" );
753 ah.atphd_ctrlinfo = ATP_TRESP | ATP_EOM;
754 if ( ah.atphd_bitmap != 1 ) {
755 syslog( LOG_ERR, "zip atp bad bitmap" );
762 memcpy( &index, data, sizeof( u_short ));
763 data += sizeof( u_short );
764 index = ntohs( index );
766 syslog( LOG_INFO, "zip atp malformed packet" );
771 end = data + sizeof( packet );
772 *data++ = DDPTYPE_ATP;
773 memcpy( data, &ah, sizeof( struct atphdr ));
774 data += sizeof( struct atphdr );
775 lastflag = data++; /* mark and space for last flag */
777 nzones = data; /* mark and space for zone count */
778 data += sizeof( u_short );
781 case ZIPOP_GETMYZONE :
783 syslog( LOG_INFO, "zip atp gmz bad index" );
787 if ( iface->i_flags & IFACE_LOOPBACK ) {
788 iface = interfaces->i_next; /* first interface */
789 } else if ( ntohs( iface->i_rt->rt_firstnet ) >
790 ntohs( from->sat_addr.s_net ) ||
791 ntohs( iface->i_rt->rt_lastnet ) <
792 ntohs( from->sat_addr.s_net )) {
796 if ( iface->i_rt->rt_zt == 0 ) {
799 zt = (struct ziptab *)iface->i_rt->rt_zt->l_data;
800 if ( data + 1 + zt->zt_len > end ) {
801 syslog( LOG_INFO, "zip atp gmz reply too long" );
804 *data++ = zt->zt_len;
805 memcpy( data, zt->zt_name, zt->zt_len );
812 case ZIPOP_GETZONELIST :
813 for ( zt = ziptab; zt && ( index > 1 ); zt = zt->zt_next, index-- )
815 for ( nz = 0; zt; zt = zt->zt_next, nz++ ) {
816 if ( data + 1 + zt->zt_len > end ) {
819 *data++ = zt->zt_len;
820 memcpy( data, zt->zt_name, zt->zt_len );
824 *lastflag = ( zt == 0 ); /* Too clever? */
827 case ZIPOP_GETLOCALZONES :
828 if ( iface->i_flags & IFACE_LOOPBACK ) {
829 iface = interfaces->i_next; /* first interface */
830 } else if ( ntohs( iface->i_rt->rt_firstnet ) >
831 ntohs( from->sat_addr.s_net ) ||
832 ntohs( iface->i_rt->rt_lastnet ) <
833 ntohs( from->sat_addr.s_net )) {
837 for ( l = iface->i_rt->rt_zt; l && ( index > 1 );
838 l = l->l_next, index-- )
840 for ( nz = 0; l; l = l->l_next, nz++ ) {
841 zt = (struct ziptab *)l->l_data;
842 if ( data + 1 + zt->zt_len > end ) {
845 *data++ = zt->zt_len;
846 memcpy( data, zt->zt_name, zt->zt_len );
850 *lastflag = ( l == 0 );
854 syslog( LOG_INFO, "zip atp bad option" );
861 memcpy( nzones, &nz, sizeof( u_short ));
862 if ( sendto( ap->ap_fd, packet, data - packet, 0,
863 (struct sockaddr *)from,
864 sizeof( struct sockaddr_at )) < 0 ) {
865 syslog( LOG_ERR, "zip atp sendto %u.%u: %m",
866 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
873 syslog( LOG_INFO, "zip_packet bad ddp type from %u.%u\n",
874 ntohs( from->sat_addr.s_net ), from->sat_addr.s_node );
881 int zip_getnetinfo( iface )
882 struct interface *iface;
886 struct sockaddr_at sat;
887 char *data, packet[ 40 ];
890 syslog( LOG_INFO, "zip_getnetinfo for %s", iface->i_name );
892 for ( ap = iface->i_ports; ap; ap = ap->ap_next ) {
893 if ( ap->ap_packet == zip_packet ) {
898 syslog( LOG_ERR, "zip_getnetinfo can't find zip socket!" );
904 *data++ = DDPTYPE_ZIP;
906 zh.zh_op = ZIPOP_GNI;
908 memcpy( data, &zh, sizeof( struct ziphdr ));
909 data += sizeof( struct ziphdr );
911 memcpy( data, &net, sizeof( u_short ));
912 data += sizeof( u_short );
913 memcpy( data, &net, sizeof( u_short ));
914 data += sizeof( u_short );
917 * Set our requesting zone to NULL, so the response will contain
923 sat.sat_len = sizeof( struct sockaddr_at );
925 sat.sat_family = AF_APPLETALK;
926 sat.sat_addr.s_net = 0;
927 sat.sat_addr.s_node = ATADDR_BCAST;
928 sat.sat_port = ap->ap_port;
930 if ( sendto( ap->ap_fd, packet, data - packet, 0, (struct sockaddr *)&sat,
931 sizeof( struct sockaddr_at )) < 0 ) {
932 syslog( LOG_ERR, "zip_getnetinfo sendto: %m" );
945 if (( zt = (struct ziptab *)calloc(1, sizeof( struct ziptab ))) == NULL ) {
950 if (( zt->zt_name = (char *)malloc( len )) == NULL ) {
955 memcpy( zt->zt_name, name, len );
961 * Insert at the end. Return 1 if a mapping already exists, 0 otherwise.
964 static int add_list( head, data )
970 for ( l = *head; l; l = l->l_next ) {
971 if ( l->l_data == data ) {
975 if (( l = (struct list *)malloc( sizeof( struct list ))) == NULL ) {
976 syslog( LOG_ERR, "add_list malloc: %m" );
982 if ( *head == NULL ) {
986 /* find end of list */
987 for ( l2 = *head; l2->l_next; l2 = l2->l_next )
995 int addzone( rt, len, zone )
1003 for ( zt = ziptab; zt; zt = zt->zt_next ) {
1004 if ( zt->zt_len == len &&
1005 strndiacasecmp( zt->zt_name, zone, len ) == 0 ) {
1010 if (( zt = newzt( len, zone )) == NULL ) {
1011 syslog( LOG_ERR, "addzone newzt: %m" );
1014 if ( ziptab == NULL ) {
1018 zt->zt_prev = ziplast;
1019 ziplast->zt_next = zt;
1024 if ((cc = add_list( &zt->zt_rt, rt )) < 0)
1030 if ((cc = add_list( &rt->rt_zt, zt )) < 0 )
1035 syslog( LOG_ERR, "addzone corrupted route/zone mapping" );
1039 * We get the repeat for local nets which have zone information
1040 * already: we ask anyway, just to make sure.
1046 syslog( LOG_ERR, "addzone corrupted zone/route mapping" );