xnu-792.18.15.tar.gz
[apple/xnu.git] / bsd / netat / ddp_r_zip.c
index 573fda9e56382092b02d638665edb308b47e1341..5f715350a3278cd3e6d65883a54a25f7b5fa9d99 100644 (file)
@@ -1,23 +1,29 @@
 /*
  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  *     Copyright (c) 1988-1998 Apple Computer, Inc. 
@@ -68,6 +74,8 @@
 #include <netat/routing_tables.h>
 #include <netat/debug.h>
 
+#include <sys/kern_event.h>
+
 static void zip_reply_to_getmyzone();
 extern int at_reg_mcast(), at_unreg_mcast();
 
@@ -87,8 +95,8 @@ extern short  ErrorZIPoverflow;
 static int     netinfo_reply_pending;
 static void    zip_netinfo_reply(at_x_zip_t *, at_ifaddr_t *);
 static void    zip_getnetinfo(at_ifaddr_t *);
-static void    zip_getnetinfo_funnel(at_ifaddr_t *);
-static void    send_phony_reply(gbuf_t *);
+static void    zip_getnetinfo_locked(void *);
+static void    send_phony_reply(void *);
 
 /*
  * zip_send_getnetinfo_reply: we received a GetNetInfo packet, we need to reply
@@ -438,7 +446,7 @@ static void zip_send_reply_to_query(mreceived, ifID)
 
        /* access the number of nets requested in the Query */
        network_count  = *((char *)(ddp_received->data) + 1);
-       NetAsked = (u_short *)(ddp_received->data+ 2);
+       NetAsked = (u_short *)(ddp_received->data + 2);
 
        /* check the validity of the Query packet */
 
@@ -476,7 +484,7 @@ newPacket:
        reply_length = 2;       /* 1st byte is ZIP reply code, 2nd is network count */
 
        for (i = 0 ; i < network_count ; i ++, NetAsked++) {
-         Entry = rt_blookup(*NetAsked);
+         Entry = rt_blookup(ntohs(*NetAsked));
 
          if (Entry != NULL && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
              RT_ALL_ZONES_KNOWN(Entry)) { /* this net is well known... */
@@ -539,7 +547,7 @@ newPacket:
                         * and build a separate packet for each extended network requested
                         */
 
-               zip_send_ext_reply_to_query(mreceived, ifID, Entry, *NetAsked);
+               zip_send_ext_reply_to_query(mreceived, ifID, Entry, ntohs(*NetAsked));
 
            }
          }
@@ -577,7 +585,7 @@ void zip_router_input (m, ifID)
        register at_ddp_t       *ddp;
        register at_atp_t       *atp;
        register at_zip_t       *zip;
-       register u_long  user_bytes;
+       u_char   user_bytes[4];
        register u_short user_byte;
        
        /* variables for ZipNotify processing */
@@ -723,6 +731,10 @@ void zip_router_input (m, ifID)
                        bcopy((caddr_t)new_zone, (caddr_t)&ifID->ifZoneName, 
                              new_zone_len+1);
 
+                       /* Send network zone change event and new zone for this interface. */
+                       atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ZONEUPDATED, 0, &(ifID->ifZoneName));
+                       atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ZONELISTCHANGED, 0, 0);
+                       
                        /* add the new zone to the list of local zones */
                        if (!MULTIPORT_MODE && !DEFAULT_ZONE(&ifID->ifZoneName))
                                (void)setLocalZones(&ifID->ifZoneName, 
@@ -736,6 +748,7 @@ void zip_router_input (m, ifID)
                         */
                        ifID->ifNumRetries = ZIP_NETINFO_RETRIES;
                        netinfo_reply_pending = 1;
+                       ifID->ifGNIScheduled = 1;
                        timeout(zip_sched_getnetinfo, (caddr_t) ifID, 
                                 2*ZIP_TIMER_INT);
        
@@ -755,8 +768,8 @@ void zip_router_input (m, ifID)
 
                /* Get the user bytes in network order */
 
-               user_bytes = UAL_VALUE(atp->user_bytes);
-               user_byte = user_bytes >> 24; /* Get the zeroth byte */
+               *((u_long*)user_bytes) = UAL_VALUE(atp->user_bytes);
+               user_byte = user_bytes[0]; /* Get the zeroth byte */
 
                dPrintf(D_M_ZIP, D_L_INPUT,
                        ("zip_input: received a ZIP_ATP command=%d\n", user_byte));
@@ -864,8 +877,10 @@ static void zip_netinfo_reply (netinfo, ifID)
         * to us.
         */
        /* *** Do we really need to check this? *** */
-       if (!zonename_equal((at_nvestr_t *)netinfo->data, &ifID->ifZoneName))
+       if (!zonename_equal((at_nvestr_t *)netinfo->data, &ifID->ifZoneName)) {
+               dPrintf(D_M_ZIP, D_L_INFO, ("zip_netinfo_reply, !zonename_equal!!!"));
                return;
+       }
 
        ifID->ifThisCableStart = NET_VALUE(netinfo->cable_range_start);
        ifID->ifThisCableEnd = NET_VALUE(netinfo->cable_range_end);
@@ -873,6 +888,7 @@ static void zip_netinfo_reply (netinfo, ifID)
                 ifID->ifThisCableStart, ifID->ifThisCableEnd));
 
        /* The packet is in response to our request */
+       ifID->ifGNIScheduled = 0;
        untimeout (zip_sched_getnetinfo, (caddr_t) ifID);
        netinfo_reply_pending = 0;
        zone_name_len = netinfo->data[0];
@@ -932,6 +948,12 @@ static void zip_netinfo_reply (netinfo, ifID)
                ZIPwakeup(ifID, ZIP_RE_AARP);
                return;
        }
+       
+       if (!ifID->startup_inprogress) {
+               /* Send event with zone info. This covers case where we get zone info
+                       after startup. During startup this event is sent from ZIPwakeup. */
+               atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ZONEUPDATED, 0, &(ifID->ifZoneName));
+       }
 
        ZIPwakeup(ifID, 0); /* no error */
        return;
@@ -951,18 +973,24 @@ int zip_control (ifID, control)
        switch (control) {
        case ZIP_ONLINE :
        case ZIP_LATE_ROUTER :
-               ifID->ifNumRetries = 0;
-               /* Get the desired zone name from elap and put it in
-                * ifID for zip_getnetinfo() to use.
-                */
-               if (ifID->startup_zone.len)
-                       ifID->ifZoneName = ifID->startup_zone;
-               zip_getnetinfo(ifID);
+               if (!ifID->ifGNIScheduled) {
+                       ifID->ifNumRetries = 0;
+                       /* Get the desired zone name from elap and put it in
+                       * ifID for zip_getnetinfo() to use.
+                       */
+                       if (ifID->startup_zone.len)
+                               ifID->ifZoneName = ifID->startup_zone;
+                       zip_getnetinfo(ifID);
+               }
                break;
        case ZIP_NO_ROUTER :
                ifID->ifZoneName.len = 1;
                ifID->ifZoneName.str[0] = '*';
                ifID->ifZoneName.str[1] = '\0';
+
+               /* Send event with zone info. */
+               atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ZONEUPDATED, 0, &(ifID->ifZoneName));
+
                break;
        default :
                break;
@@ -970,13 +998,19 @@ int zip_control (ifID, control)
        return (0);
 }
 
-/* funnel version of zip_getnetinfo */
-static void zip_getnetinfo_funnel(ifID)
-     register at_ifaddr_t       *ifID;
+/* locked version of zip_getnetinfo */
+static void zip_getnetinfo_locked(arg)
+     void       *arg;
 {
-        thread_funnel_set(network_flock, TRUE);
-       zip_getnetinfo(ifID);
-        thread_funnel_set(network_flock, FALSE);
+       at_ifaddr_t       *ifID;
+       
+       atalk_lock();
+       if (ifID != NULL) {             // make sure it hasn't been closed
+               ifID = (at_ifaddr_t *)arg;
+               ifID->ifGNIScheduled = 0;
+               zip_getnetinfo(ifID);
+       }
+       atalk_unlock();
 }
 
 
@@ -993,6 +1027,7 @@ static void zip_getnetinfo (ifID)
        void                    zip_sched_getnetinfo();
        register struct atalk_addr      *at_dest;
        register int            size;
+       
 
        size =  DDP_X_HDR_SIZE + ZIP_X_HDR_SIZE + ifID->ifZoneName.len + 1
                + sizeof(struct atalk_addr) + 1;
@@ -1003,7 +1038,8 @@ static void zip_getnetinfo (ifID)
                 */
                dPrintf(D_M_ZIP, D_L_WARNING, ("zip_getnetinfo: no buffer, call later port=%d\n",
                        ifID->ifPort));
-               timeout (zip_getnetinfo_funnel, (caddr_t) ifID, ZIP_TIMER_INT/10);
+               ifID->ifGNIScheduled = 1;
+               timeout (zip_getnetinfo_locked, (caddr_t) ifID, ZIP_TIMER_INT/10);
                return;
        }
 
@@ -1056,7 +1092,7 @@ static void zip_getnetinfo (ifID)
 
        ifID->ifNumRetries++;
        netinfo_reply_pending = 1;
-
+       ifID->ifGNIScheduled = 1;
        timeout (zip_sched_getnetinfo, (caddr_t) ifID, ZIP_TIMER_INT);
 } /* zip_getnetinfo */
 
@@ -1069,9 +1105,10 @@ static void zip_getnetinfo (ifID)
 void   zip_sched_getnetinfo (ifID)
      register at_ifaddr_t           *ifID;
 {
-       boolean_t       funnel_state;
 
-       funnel_state = thread_funnel_set(network_flock, TRUE);
+       atalk_lock();
+       
+       ifID->ifGNIScheduled = 0;
 
        if (ifID->ifNumRetries >= ZIP_NETINFO_RETRIES) {
                /* enough packets sent.... give up! */
@@ -1100,7 +1137,7 @@ void      zip_sched_getnetinfo (ifID)
        } else
                zip_getnetinfo(ifID);
 
-       (void) thread_funnel_set(network_flock, FALSE);
+       atalk_unlock();
 }
 
 
@@ -1121,7 +1158,7 @@ int zip_type_packet (m)
        register at_atp_t       *atp;
        register at_ddp_t       *ddp;
        register at_zip_t       *zip;
-       register u_long user_bytes;
+       u_char  user_bytes[4];
        register int    user_byte;
 
        ddp = (at_ddp_t *)gbuf_rptr(m);
@@ -1140,8 +1177,8 @@ int zip_type_packet (m)
                        else
                                atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
                        /* Get the user bytes in network order */
-                       user_bytes = UAL_VALUE(atp->user_bytes);
-                       user_byte = user_bytes >> 24; /* Get the zeroth byte */
+                       *((u_long*)user_bytes) = UAL_VALUE(atp->user_bytes);
+                       user_byte = user_bytes[0]; /* Get the zeroth byte */
                        if ((user_byte == ZIP_GETMYZONE) ||
                            (user_byte == ZIP_GETZONELIST) ||
                            (user_byte == ZIP_GETLOCALZONES))
@@ -1227,8 +1264,7 @@ int zip_handle_getmyzone(ifID, m)
         r_atp->bitmap = 0;
         UAS_UAS(r_atp->tid, atp->tid);
         ulongtmp = 1;
-        ulongtmp = htonl(ulongtmp);
-       UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* no of zones */
+               UAL_ASSIGN_HTON(r_atp->user_bytes, ulongtmp); /* no of zones */
 
         /* fill up atp data part */
         bcopy((caddr_t) &ifID->ifZoneName, (caddr_t) r_atp->data, ifID->ifZoneName.len+1);
@@ -1240,16 +1276,15 @@ int zip_handle_getmyzone(ifID, m)
 }
 
 static void
-send_phony_reply(rm)
-       gbuf_t  *rm;
+send_phony_reply(arg)
+       void    *arg;
 {
-       boolean_t       funnel_state;
+       gbuf_t  *rm = (gbuf_t *)arg;
 
-       funnel_state = thread_funnel_set(network_flock, TRUE);
-        
+       atalk_lock();
        ddp_input(rm, ifID_home);
+       atalk_unlock();
         
-       (void) thread_funnel_set(network_flock, FALSE);
        return;
 }
 
@@ -1443,7 +1478,7 @@ zip_reply_received(m, ifID, reply_type)
 
        /* access the number of nets provided in the ZIP Reply */
 
-       network_count  = *(u_char *)(gbuf_rptr(m) + DDP_X_HDR_SIZE + 1);
+       network_count  = ntohs(*(u_char *)(gbuf_rptr(m) + DDP_X_HDR_SIZE + 1));
 
        PacketPtr = (char *)(gbuf_rptr(m) + DDP_X_HDR_SIZE + 2);
 
@@ -1455,7 +1490,7 @@ zip_reply_received(m, ifID, reply_type)
 
        while (payload_len > 0 && network_count >0) {
 
-               Network = *(at_net_al *)PacketPtr;
+               Network = ntohs(*(at_net_al *)PacketPtr);
                PacketPtr += 2;
                zname = (at_nvestr_t *)PacketPtr;
                if (payload_len)
@@ -1585,8 +1620,7 @@ static void zip_reply_to_getmyzone (ifID, m)
         r_atp->bitmap = 0;
         UAS_UAS(r_atp->tid, atp->tid);
         ulongtmp = 1;
-        ulongtmp = htonl(ulongtmp);
-       UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* no of zones */
+               UAL_ASSIGN_HTON(r_atp->user_bytes, ulongtmp); /* no of zones */
 
        data_ptr = (char *)r_atp->data;
 
@@ -1683,7 +1717,7 @@ zip_reply_to_getzonelist (ifID, m)
 
                        /* get the start index from the ATP request */
 
-               StartPoint = (UAL_VALUE(atp->user_bytes) & 0xffff) -1;
+               StartPoint = (UAL_VALUE_NTOH(atp->user_bytes) & 0xffff) -1;
 
                /* find the next zone to send */
 
@@ -1724,7 +1758,7 @@ zip_reply_to_getzonelist (ifID, m)
                                ulongtmp += 0x01000000;
 
         
-               UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* # of zones and flag*/
+               UAL_ASSIGN_HTON(r_atp->user_bytes, ulongtmp); /* # of zones and flag*/
 
         size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + PacketLen;
         gbuf_winc(rm,size);
@@ -1795,7 +1829,7 @@ int zip_reply_to_getlocalzones (ifID, m)
 
        /* get the start index from the ATP request */
 
-       Index_wanted = (UAL_VALUE(atp->user_bytes) & 0xffff) -1;
+       Index_wanted = (UAL_VALUE_NTOH(atp->user_bytes) & 0xffff) -1;
 
        dPrintf(D_M_ZIP_LOW, D_L_INFO, 
                ("zip_r_GLZ: for station %d:%d Index_wanted = %d\n",
@@ -1923,7 +1957,7 @@ FullPacket:
         r_atp->bitmap = 0;
         UAS_UAS(r_atp->tid, atp->tid);
         ulongtmp =  ((last_flag << 24) & 0xFF000000) + ZonesInPacket; /* # of zones and flag*/
-       UAL_ASSIGN(r_atp->user_bytes, ulongtmp);
+               UAL_ASSIGN_HTON(r_atp->user_bytes, ulongtmp);
         size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + packet_len;
         gbuf_winc(rm,size);
         DDPLEN_ASSIGN(r_ddp, size);