]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
More DLPI patches from Joost. His patch was way garbled, but this is my
authorBen Cottrell <source@isc.org>
Fri, 16 Mar 2001 22:12:19 +0000 (22:12 +0000)
committerBen Cottrell <source@isc.org>
Fri, 16 Mar 2001 22:12:19 +0000 (22:12 +0000)
best interpretation of it. The only thing confusing me is that I thought
he'd fixed all the byte order dependencies in an elegant way, but I
still see some rather ugly #ifdefs in this code. Oh well. At least it
works on minbar.

common/dlpi.c
includes/dhcpd.h

index ca33fbee15ddfdf3056eb08b3025cf9f11a40c34..1421dee7a294d12705423ad4e8193dde2cb3b506 100644 (file)
@@ -84,7 +84,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dlpi.c,v 1.26 2001/02/02 18:14:17 tamino Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dlpi.c,v 1.27 2001/03/16 22:12:18 tamino Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -130,15 +130,7 @@ static int strioctl PROTO ((int fd, int cmd, int timeout, int len, char *dp));
 #define DLPI_MAXDLBUF          8192    /* Buffer size */
 #define DLPI_MAXDLADDR         1024    /* Max address size */
 #define DLPI_DEVDIR            "/dev/" /* Device directory */
-#define DLPI_DEFAULTSAP                0x0800  /* IP protocol */
-
-static void dlpi_makeaddr PROTO ((unsigned char *physaddr, int physaddrlen,
-                                 unsigned char *sap, int saplen,
-                                 unsigned char *buf));
-static void dlpi_parseaddr PROTO ((unsigned char *buf,
-                                  unsigned char *physaddr,
-                                  int physaddrlen, unsigned char *sap,
-                                  int saplen));
+
 static int dlpiopen PROTO ((char *ifname));
 static int dlpiunit PROTO ((char *ifname));
 static int dlpiinforeq PROTO ((int fd));
@@ -211,13 +203,10 @@ int if_register_dlpi (info)
            log_fatal ("Can't open DLPI device for %s: %m", info -> name);
        }
 
-       /*
-        * Get information about the provider.
-        */
 
        /*
-        * Submit a DL_INFO_REQ request, to find
-        * the dl_mac_type and dl_provider_style
+       * Submit a DL_INFO_REQ request, to find the dl_mac_type and 
+         * dl_provider_style
         */
        if (dlpiinforeq(sock) < 0 || dlpiinfoack(sock, (char *)buf) < 0) {
            log_fatal ("Can't get DLPI MAC type for %s: %m", info -> name);
@@ -235,11 +224,21 @@ int if_register_dlpi (info)
                info -> hw_address.hbuf [0] = HTYPE_FDDI;
                break;
              default:
-               log_fatal ("%s: unknown DLPI MAC type %ld",
-                      info -> name,
-                      dlp -> info_ack.dl_mac_type);
+              log_fatal ("%s: unsupported DLPI MAC type %ld",
+                     info -> name, dlp -> info_ack.dl_mac_type);
                break;
            }
+            /*
+             * copy the sap length and broadcast address of this interface
+             * to interface_info. This fixes nothing but seemed nicer than to
+             * assume -2 and ffffff.
+             */
+            info -> dlpi_sap_length = dlp -> info_ack.dl_sap_length;
+            info -> dlpi_broadcast_addr.hlen = 
+             dlp -> info_ack.dl_brdcst_addr_length;
+            memcpy (info -> dlpi_broadcast_addr.hbuf, 
+             (char *)dlp + dlp -> info_ack.dl_brdcst_addr_offset, 
+             dlp -> info_ack.dl_brdcst_addr_length);
        }
 
        if (dlp -> info_ack.dl_provider_style == DL_STYLE2) {
@@ -258,7 +257,7 @@ int if_register_dlpi (info)
        /*
         * Bind to the IP service access point (SAP), connectionless (CLDLS).
         */
-       if (dlpibindreq (sock, DLPI_DEFAULTSAP, 0, DL_CLDLS, 0, 0) < 0
+      if (dlpibindreq (sock, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0) < 0
            || dlpibindack (sock, (char *)buf) < 0) {
            log_fatal ("Can't bind DLPI device for %s: %m", info -> name);
        }
@@ -404,8 +403,8 @@ void if_register_receive (info)
 {
 #ifdef USE_DLPI_PFMOD
        struct packetfilt pf;
-       struct ip iphdr;
-       u_short offset;
+        struct ip iphdr;
+        u_int16_t offset;
 #endif
 
        /* Open a DLPI device and hang it on this interface... */
@@ -421,17 +420,16 @@ void if_register_receive (info)
 
 #if defined (USE_DLPI_RAW)
 # define ETHER_H_PREFIX (14) /* sizeof (ethernet_header) */
-       /*
-        * ethertype == ETHERTYPE_IP
-        */
-       offset = 12;
-       pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
-       pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_EQ;
-       pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
+    /*
+     * ethertype == ETHERTYPE_IP
+     */
+    offset = 12;
+    pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
+    pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
+    pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
 # else
 # define ETHER_H_PREFIX (0)
 # endif /* USE_DLPI_RAW */
-
        /*
         * The packets that will be received on this file descriptor
         * will be IP packets (due to the SAP that was specified in
@@ -445,28 +443,21 @@ void if_register_receive (info)
         /*
          * BOOTPS destination port
          */
-        offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_short);
+        offset = ETHER_H_PREFIX + sizeof (iphdr) + sizeof (u_int16_t);
         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
-        pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_EQ;
-        /* local_port is already in network byte order */
+        pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
         pf.Pf_Filter [pf.Pf_FilterLen++] = local_port;
-# if defined (USE_DLPI_RAW)
-        /* AND this result with the result of ETHERTYPE_IP */
-        pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_AND;
-# endif
+
         /*
          * protocol should be udp. this is a byte compare, test for
          * endianess.
          */
-        offset = ETHER_H_PREFIX + ((u_char *)&(iphdr.ip_p) - (u_char *) &iphdr);
+        offset = ETHER_H_PREFIX + ((u_int8_t *)&(iphdr.ip_p) - (u_int8_t *)&iphdr);
         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + (offset / 2);
         pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_AND;
         pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0x00FF);
-        pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_EQ;
-        pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
-        /* AND this result with the result of local_port */
-        pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_AND;
-
+        pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT | ENF_CAND;
+      pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
 
        /* Install the filter... */
        if (strioctl (info -> rfdesc, PFIOCSETF, INFTIM,
@@ -532,10 +523,8 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
        double ih [1536 / sizeof (double)];
        unsigned char *dbuf = (unsigned char *)ih;
        unsigned dbuflen;
-       unsigned char sap [2];
        unsigned char dstaddr [DLPI_MAXDLADDR];
        unsigned addrlen;
-       int saplen;
        int result;
        int fudge;
 
@@ -548,8 +537,8 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
        /* Assemble the headers... */
 #ifdef USE_DLPI_RAW
        assemble_hw_header (interface, (unsigned char *)hh, &dbuflen, hto);
-       if (dbuflen > sizeof hh) /* hh is too small! */
-               abort ();
+      if (dbuflen > sizeof hh)
+              log_fatal ("send_packet: hh buffer too small.\n");
        fudge = dbuflen % 4; /* IP header must be word-aligned. */
        memcpy (dbuf + fudge, (unsigned char *)hh, dbuflen);
        dbuflen += fudge;
@@ -567,46 +556,52 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
 #ifdef USE_DLPI_RAW
        result = write (interface -> wfdesc, dbuf + fudge, dbuflen - fudge);
 #else
-       /*
-        * a bug on intel causes a sap type of 0x0800 to appear on the wire as 0x0000.
-        * a bug on intel causes a sap type of 0x0000 to appear on the wire as 0x0800.
-        * .uhhmmm..
-        *
-        * at least the elxl (3com) and iprb (intel) drivers `need' this hack on 2.8.
-        */
-#if defined (SOL_X86_DLPI_SAP_HACK)
-       sap [0] = 0x00;
-       sap [1] = 0x00;
-#else                   /* sparc and others, as it should be. */
-       sap [0] = 0x08;
-       sap [1] = 0x00;
-#endif
-
-       saplen = -2;            /* -2 indicates a two byte SAP at the end
-                                  of the address */
 
-       /* Setup the destination address */
-       if (hto && hto -> hlen == interface -> hw_address.hlen) {
-               dlpi_makeaddr (&hto -> hbuf [1],
-                              hto -> hlen - 1, sap, saplen, dstaddr);
-       } else {
-           /* XXX: Assumes broadcast addr is all ones */
-           /* Really should get the broadcast address as part of the
-            * dlpiinforeq, and store it somewhere in the interface structure.
-            */
-           unsigned char bcast_ether [DLPI_MAXDLADDR];
+       /*
+         * Setup the destination address (DLSAP) in dstaddr 
+         *
+         * If sap_length < 0 we must deliver the DLSAP as phys+sap. 
+         * If sap_length > 0 we must deliver the DLSAP as sap+phys.
+         *
+         * sap = Service Access Point == ETHERTYPE_IP
+         * sap + datalink address is called DLSAP in dlpi speak.
+         */
+        { /* ENCODE DLSAP */
+          unsigned char phys [DLPI_MAXDLADDR];
+          unsigned char sap [4];
+          int sap_len = interface -> dlpi_sap_length;
+          int phys_len = interface -> hw_address.hlen - 1;
+
+          /* sap = htons (ETHERTYPE_IP) kludge */
+          memset (sap, 0, sizeof (sap));
+# if (BYTE_ORDER == LITTLE_ENDIAN)
+          sap [0] = 0x00;
+          sap [1] = 0x08;
+# else
+          sap [0] = 0x08;
+          sap [1] = 0x00;
+# endif
 
-           memset ((char *)bcast_ether, 0xFF,
-                   interface -> hw_address.hlen - 1);
-           dlpi_makeaddr (bcast_ether, interface -> hw_address.hlen - 1,
-                          sap, saplen, dstaddr);
-       }
-       addrlen = interface -> hw_address.hlen - 1 + ABS (saplen);
+        if (hto && hto -> hlen == interface -> hw_address.hlen)
+             memcpy ( phys, (char *) &hto -> hbuf [1], phys_len);
+          else 
+             memcpy ( phys, interface -> dlpi_broadcast_addr.hbuf, 
+              interface -> dlpi_broadcast_addr.hlen);
+           
+          if (sap_len < 0) { 
+             memcpy ( dstaddr, phys, phys_len);
+             memcpy ( (char *) &dstaddr [phys_len], sap, ABS (sap_len));
+          }
+          else {
+             memcpy ( dstaddr, (void *) sap, sap_len);
+             memcpy ( (char *) &dstaddr [sap_len], phys, phys_len);
+          }
+        addrlen = phys_len + ABS (sap_len);
+      } /* ENCODE DLSAP */
 
-       /* Send the packet down the wire... */
        result = dlpiunitdatareq (interface -> wfdesc, dstaddr, addrlen,
                                  0, 0, dbuf, dbuflen);
-#endif
+#endif /* USE_DLPI_RAW */
        if (result < 0)
                log_error ("send_packet: %m");
        return result;
@@ -622,10 +617,8 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
        struct hardware *hfrom;
 {
        unsigned char dbuf [1536];
-       unsigned char sap [2];
        unsigned char srcaddr [DLPI_MAXDLADDR];
        unsigned long srcaddrlen;
-       int saplen;
        int flags = 0;
        int length = 0;
        int offset = 0;
@@ -644,20 +637,36 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
            return length;
        }
 
-#ifndef USE_DLPI_RAW
-       /* Copy sender info */
-       /* XXX: Assumes ethernet, where SAP comes at end of haddr */
-       saplen = -2;
-       if (hfrom && (srcaddrlen ==
-                     ABS (saplen) + interface -> hw_address.hlen - 1)) {
-               hfrom -> hbuf [0] = interface -> hw_address.hbuf [0];
-               hfrom -> hlen = interface -> hw_address.hlen;
-               dlpi_parseaddr (srcaddr, &hfrom -> hbuf [1],
-                               interface -> hw_address.hlen - 1, sap, saplen);
-       } else if (hfrom) {
-               memset (hfrom, '\0', sizeof *hfrom);
-       }
-#endif
+# if !defined (USE_DLPI_RAW)
+        /*
+         * Copy the sender's hw address into hfrom
+         * If sap_len < 0 the DLSAP is as phys+sap.
+         * If sap_len > 0 the DLSAP is as sap+phys.
+         *
+         * sap is discarded here.
+         */
+        { /* DECODE DLSAP */
+          int sap_len = interface -> dlpi_sap_length;
+          int phys_len = interface -> hw_address.hlen - 1;
+
+          if (hfrom && (srcaddrlen == ABS (sap_len) + phys_len )) {
+            hfrom -> hbuf [0] = interface -> hw_address.hbuf [0];
+            hfrom -> hlen = interface -> hw_address.hlen;
+            
+            if (sap_len < 0) {
+              memcpy ((char *) &hfrom -> hbuf [1], srcaddr, phys_len);
+            }
+            else {
+              memcpy ((char *) &hfrom -> hbuf [1], (char *) &srcaddr [phys_len],
+                phys_len);
+            }
+          } 
+          else if (hfrom) {
+            memset (hfrom, '\0', sizeof *hfrom);
+          }
+        } /* DECODE_DLSAP */
+
+# endif /* !defined (USE_DLPI_RAW) */
 
        /* Decode the IP and UDP headers... */
        bufix = 0;
@@ -711,45 +720,6 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
 
 #define DLPI_MAXWAIT           15      /* Max timeout */
 
-static void dlpi_makeaddr (physaddr, physaddrlen, sap, saplen, buf)
-       unsigned char *physaddr;
-       int physaddrlen;
-       unsigned char *sap;
-       int saplen;
-       unsigned char *buf;
-{
-       /*
-        * If the saplen is negative, the SAP goes at the end of the address,
-        * otherwise it goes at the beginning.
-        */
-       if (saplen >= 0) {
-               memcpy ((char *)buf, (char *)sap, saplen);
-               memcpy ((char *)&buf [saplen], (char *)physaddr, physaddrlen);
-       } else {
-               memcpy ((char *)buf, (char *)physaddr, physaddrlen);
-               memcpy ((char *)&buf [physaddrlen], (char *)sap, 0 - saplen);
-       }
-}
-
-static void dlpi_parseaddr (buf, physaddr, physaddrlen, sap, saplen)
-       unsigned char *buf;
-       unsigned char *physaddr;
-       int physaddrlen;
-       unsigned char *sap;
-       int saplen;
-{
-       /*
-        * If the saplen is negative, the SAP is at the end of the address,
-        * otherwise it is at the beginning.
-        */
-       if (saplen >= 0) {
-               memcpy ((char *)sap, (char *)buf, saplen);
-               memcpy ((char *)physaddr, (char *)&buf [saplen], physaddrlen);
-       } else {
-               memcpy ((char *)physaddr, (char *)buf, physaddrlen);
-               memcpy ((char *)sap, (char *)&buf [physaddrlen], 0 - saplen);
-       }
-}
 
 /*
  * Parse an interface name and extract the unit number
index 6e4de83050353593f668ba3dd49977676f2e5239..3e8ba90e4826b64655eca11d95fe60985f7901b4 100644 (file)
@@ -756,6 +756,10 @@ struct interface_info {
 
        /* Only used by DHCP client code. */
        struct client_state *client;
+# if defined (USE_DLPI_SEND) || defined (USE_DLPI_RECEIVE)
+       int dlpi_sap_length;
+       struct hardware dlpi_broadcast_addr;
+# endif /* DLPI_SEND || DLPI_RECEIVE */
 };
 
 struct hardware_link {