components/quagga/patches/25-isisd-dlpi.patch
branchs11-sru
changeset 2239 f0bde9a421fe
parent 2238 cc3545c342fd
child 2240 de14ec92a8a8
equal deleted inserted replaced
2238:cc3545c342fd 2239:f0bde9a421fe
     1 diff --git a/ChangeLog b/ChangeLog
       
     2 index 38ea66d..ad1c40c 100644
       
     3 --- ChangeLog
       
     4 +++ ChangeLog
       
     5 @@ -1,3 +1,8 @@
       
     6 +2007-08-07 James Carlson <[email protected]>
       
     7 +
       
     8 +	* configure.ac: Added support for separate link-layer access
       
     9 +	  mechanisms in isisd.
       
    10 +
       
    11  2007-07-27 Paul Jakma <[email protected]>
       
    12  
       
    13  	* configure.ac: Bump version to 0.99.8
       
    14 diff --git a/configure.ac b/configure.ac
       
    15 index 857f415..437767e 100755
       
    16 --- configure.ac
       
    17 +++ configure.ac
       
    18 @@ -750,6 +750,35 @@
       
    19  AC_SUBST(KERNEL_METHOD)
       
    20  AC_SUBST(OTHER_METHOD)
       
    21  
       
    22 +dnl --------------------------
       
    23 +dnl Determine IS-IS I/O method
       
    24 +dnl --------------------------
       
    25 +AC_CHECK_HEADER(net/bpf.h)
       
    26 +AC_CHECK_HEADER(sys/dlpi.h)
       
    27 +AC_MSG_CHECKING(zebra IS-IS I/O method)
       
    28 +if test x"$opsys" = x"gnu-linux"; then
       
    29 +  AC_MSG_RESULT(pfpacket)
       
    30 +  ISIS_METHOD=isis_pfpacket.o
       
    31 +elif test x"$opsys" = x"sol2-6" -o x"$opsys" = x"sol8"; then
       
    32 +  AC_MSG_RESULT(DLPI)
       
    33 +  ISIS_METHOD="isis_dlpi.o"
       
    34 +else
       
    35 +  if test $ac_cv_header_net_bpf_h = no; then
       
    36 +    if test $ac_cv_header_sys_dlpi_h = no; then
       
    37 +      AC_MSG_RESULT(none)
       
    38 +      AC_MSG_WARN([*** IS-IS support will not be built ***])
       
    39 +      ISISD=""
       
    40 +    else
       
    41 +      AC_MSG_RESULT(DLPI)
       
    42 +    fi
       
    43 +    ISIS_METHOD="isis_dlpi.o"
       
    44 +  else
       
    45 +    AC_MSG_RESULT(BPF)
       
    46 +    ISIS_METHOD="isis_bpf.o"
       
    47 +  fi
       
    48 +fi
       
    49 +AC_SUBST(ISIS_METHOD)
       
    50 +
       
    51  dnl ------------------------------------
       
    52  dnl check for broken CMSG_FIRSTHDR macro
       
    53  dnl ------------------------------------
       
    54 diff --git a/isisd/ChangeLog b/isisd/ChangeLog
       
    55 index 8797af1..c2482f0 100644
       
    56 --- isisd/ChangeLog
       
    57 +++ isisd/ChangeLog
       
    58 @@ -1,3 +1,20 @@
       
    59 +2008-01-29 James Carlson <[email protected]>
       
    60 +
       
    61 +	* Fix bug #437, assert due to bogus index management 
       
    62 +	* isis_flags.c: (flags_initialize) new
       
    63 +	* (flags_get_index) fix off by one, leading to list assert
       
    64 +	  on null node data.
       
    65 +	  (flags_free_index) ditto.
       
    66 +	* isisd.c: (isis_area_create) use flags_initialize
       
    67 +	  (isis_area_destroy) deconfigure circuits when
       
    68 +	  taking down area.
       
    69 +
       
    70 +2007-07-18 James Carlson <[email protected]>
       
    71 +
       
    72 +	* isis_network.c: split up into isis_bpf.c, isis_dlpi.c, and
       
    73 +	  isis_pfpacket.c, selected by autoconf, and added DLPI support.
       
    74 +	* (general) Fixed to allow compilation and use on Solaris.
       
    75 +
       
    76  2006-12-08 Hannes Gredler <[email protected]>
       
    77  
       
    78  	* isis_adjacency.c: (isis_new_adj) Allow NULL snpa argument.
       
    79 diff --git a/isisd/Makefile.am b/isisd/Makefile.am
       
    80 index 1dd5493..859facd 100644
       
    81 --- isisd/Makefile.am
       
    82 +++ isisd/Makefile.am
       
    83 @@ -9,9 +9,11 @@ noinst_LIBRARIES = libisis.a
       
    84  sbin_PROGRAMS = isisd 
       
    85  SUBDIRS = topology
       
    86  
       
    87 +isis_method = @ISIS_METHOD@
       
    88 +
       
    89  libisis_a_SOURCES = \
       
    90  	isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \
       
    91 -	isis_tlv.c isisd.c isis_misc.c isis_network.c isis_zebra.c isis_dr.c \
       
    92 +	isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \
       
    93  	isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \
       
    94  	isis_spf.c isis_route.c isis_routemap.c
       
    95  
       
    96 @@ -26,7 +28,11 @@ noinst_HEADERS = \
       
    97  isisd_SOURCES = \
       
    98  	isis_main.c $(libisis_a_SOURCES)
       
    99  
       
   100 -isisd_LDADD = @ISIS_TOPOLOGY_LIB@ ../lib/libzebra.la @LIBCAP@
       
   101 +isisd_LDADD = $(isis_method) @ISIS_TOPOLOGY_LIB@ ../lib/libzebra.la @LIBCAP@
       
   102 +
       
   103 +isisd_DEPENDENCIES = $(isis_method)
       
   104 +
       
   105 +EXTRA_DIST = isis_bpf.c isis_dlpi.c isis_pfpacket.c
       
   106  
       
   107  examplesdir = $(exampledir)
       
   108  dist_examples_DATA = isisd.conf.sample
       
   109 diff --git a/isisd/dict.c b/isisd/dict.c
       
   110 index a333d3e..6c3e1e7 100644
       
   111 --- isisd/dict.c
       
   112 +++ isisd/dict.c
       
   113 @@ -14,12 +14,13 @@
       
   114   * into proprietary software; there is no requirement for such software to
       
   115   * contain a copyright notice related to this source.
       
   116   *
       
   117 - * $Id: dict.c,v 1.4 2005/09/25 12:04:25 hasso Exp $
       
   118 - * $Name:  $
       
   119 + * $Id$
       
   120 + * $Name$
       
   121   */
       
   122  
       
   123  #include <stdlib.h>
       
   124  #include <stddef.h>
       
   125 +#include "zebra.h"
       
   126  #include "zassert.h"
       
   127  #define DICT_IMPLEMENTATION
       
   128  #include "dict.h"
       
   129 diff --git a/isisd/include-netbsd/iso.h b/isisd/include-netbsd/iso.h
       
   130 index 714b42d..1a80aec 100644
       
   131 --- isisd/include-netbsd/iso.h
       
   132 +++ isisd/include-netbsd/iso.h
       
   133 @@ -192,7 +192,13 @@ extern struct protosw isosw[];
       
   134  #else
       
   135  /* user utilities definitions from the iso library */
       
   136  
       
   137 +#ifdef SUNOS_5
       
   138 +#define	__P(x)	x
       
   139 +#define	__BEGIN_DECLS
       
   140 +#define	__END_DECLS
       
   141 +#else
       
   142  #include <sys/cdefs.h>
       
   143 +#endif
       
   144  
       
   145  __BEGIN_DECLS
       
   146  struct iso_addr *iso_addr __P((const char *));
       
   147 diff --git a/isisd/isisd.c b/isisd/isisd.c
       
   148 index 714b42d..1a80aec 100644
       
   149 --- isisd/isisd.c
       
   150 +++ isisd/isisd.c
       
   151 @@ -130,7 +130,7 @@
       
   152    area->circuit_list = list_new ();
       
   153    area->area_addrs = list_new ();
       
   154    THREAD_TIMER_ON (master, area->t_tick, lsp_tick, area, 1);
       
   155 -  area->flags.maxindex = -1;
       
   156 +  flags_initialize (&area->flags);
       
   157    /*
       
   158     * Default values
       
   159     */
       
   160 @@ -215,7 +215,11 @@
       
   161    if (area->circuit_list)
       
   162      {
       
   163        for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit))
       
   164 -        isis_circuit_del (circuit);
       
   165 +	{
       
   166 +	  /* The fact that it's in circuit_list means that it was configured */
       
   167 +	  isis_circuit_deconfigure (circuit, area);
       
   168 +	  isis_circuit_del (circuit);
       
   169 +	}
       
   170        
       
   171        list_delete (area->circuit_list);
       
   172      }
       
   173 diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c
       
   174 new file mode 100644
       
   175 index 0000000..e66ac98
       
   176 --- /dev/null
       
   177 +++ isisd/isis_bpf.c
       
   178 @@ -0,0 +1,340 @@
       
   179 +/*
       
   180 + * IS-IS Rout(e)ing protocol - isis_bpf.c
       
   181 + *
       
   182 + * Copyright (C) 2001,2002    Sampo Saaristo
       
   183 + *                            Tampere University of Technology      
       
   184 + *                            Institute of Communications Engineering
       
   185 + *
       
   186 + * This program is free software; you can redistribute it and/or modify it 
       
   187 + * under the terms of the GNU General Public Licenseas published by the Free 
       
   188 + * Software Foundation; either version 2 of the License, or (at your option) 
       
   189 + * any later version.
       
   190 + *
       
   191 + * This program is distributed in the hope that it will be useful,but WITHOUT 
       
   192 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
       
   193 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
       
   194 + * more details.
       
   195 +
       
   196 + * You should have received a copy of the GNU General Public License along 
       
   197 + * with this program; if not, write to the Free Software Foundation, Inc., 
       
   198 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
       
   199 + */
       
   200 +
       
   201 +#include <zebra.h>
       
   202 +#include <net/if.h>
       
   203 +#include <netinet/if_ether.h>
       
   204 +#include <sys/time.h>
       
   205 +#include <sys/ioctl.h>
       
   206 +#include <net/bpf.h>
       
   207 +
       
   208 +#include "log.h"
       
   209 +#include "stream.h"
       
   210 +#include "if.h"
       
   211 +
       
   212 +#include "isisd/dict.h"
       
   213 +#include "isisd/include-netbsd/iso.h"
       
   214 +#include "isisd/isis_constants.h"
       
   215 +#include "isisd/isis_common.h"
       
   216 +#include "isisd/isis_circuit.h"
       
   217 +#include "isisd/isis_flags.h"
       
   218 +#include "isisd/isisd.h"
       
   219 +#include "isisd/isis_constants.h"
       
   220 +#include "isisd/isis_circuit.h"
       
   221 +#include "isisd/isis_network.h"
       
   222 +
       
   223 +#include "privs.h"
       
   224 +
       
   225 +extern struct zebra_privs_t isisd_privs;
       
   226 +
       
   227 +struct bpf_insn llcfilter[] = {
       
   228 +  BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN),	/* check first byte */
       
   229 +  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5),
       
   230 +  BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1),
       
   231 +  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3),	/* check second byte */
       
   232 +  BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2),
       
   233 +  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1),	/* check third byte */
       
   234 +  BPF_STMT (BPF_RET + BPF_K, (u_int) - 1),
       
   235 +  BPF_STMT (BPF_RET + BPF_K, 0)
       
   236 +};
       
   237 +int readblen = 0;
       
   238 +u_char *readbuff = NULL;
       
   239 +
       
   240 +/*
       
   241 + * Table 9 - Architectural constants for use with ISO 8802 subnetworks
       
   242 + * ISO 10589 - 8.4.8
       
   243 + */
       
   244 +
       
   245 +u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 };
       
   246 +u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 };
       
   247 +u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 };
       
   248 +u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 };
       
   249 +
       
   250 +static char sock_buff[8192];
       
   251 +
       
   252 +static int
       
   253 +open_bpf_dev (struct isis_circuit *circuit)
       
   254 +{
       
   255 +  int i = 0, fd;
       
   256 +  char bpfdev[128];
       
   257 +  struct ifreq ifr;
       
   258 +  u_int16_t blen;
       
   259 +  int true = 1, false = 0;
       
   260 +  struct timeval timeout;
       
   261 +  struct bpf_program bpf_prog;
       
   262 +
       
   263 +  do
       
   264 +    {
       
   265 +      (void) snprintf (bpfdev, sizeof (bpfdev), "/dev/bpf%d", i++);
       
   266 +      fd = open (bpfdev, O_RDWR);
       
   267 +    }
       
   268 +  while (fd < 0 && errno == EBUSY);
       
   269 +
       
   270 +  if (fd < 0)
       
   271 +    {
       
   272 +      zlog_warn ("open_bpf_dev(): failed to create bpf socket: %s",
       
   273 +		 safe_strerror (errno));
       
   274 +      return ISIS_WARNING;
       
   275 +    }
       
   276 +
       
   277 +  zlog_debug ("Opened BPF device %s", bpfdev);
       
   278 +
       
   279 +  memcpy (ifr.ifr_name, circuit->interface->name, sizeof (ifr.ifr_name));
       
   280 +  if (ioctl (fd, BIOCSETIF, (caddr_t) & ifr) < 0)
       
   281 +    {
       
   282 +      zlog_warn ("open_bpf_dev(): failed to bind to interface: %s",
       
   283 +		 safe_strerror (errno));
       
   284 +      return ISIS_WARNING;
       
   285 +    }
       
   286 +
       
   287 +  if (ioctl (fd, BIOCGBLEN, (caddr_t) & blen) < 0)
       
   288 +    {
       
   289 +      zlog_warn ("failed to get BPF buffer len");
       
   290 +      blen = circuit->interface->mtu;
       
   291 +    }
       
   292 +
       
   293 +  readblen = blen;
       
   294 +
       
   295 +  if (readbuff == NULL)
       
   296 +    readbuff = malloc (blen);
       
   297 +
       
   298 +  zlog_debug ("BPF buffer len = %u", blen);
       
   299 +
       
   300 +  /*  BPF(4): reads return immediately upon packet reception.
       
   301 +   *  Otherwise, a read will block until either the kernel
       
   302 +   *  buffer becomes full or a timeout occurs. 
       
   303 +   */
       
   304 +  if (ioctl (fd, BIOCIMMEDIATE, (caddr_t) & true) < 0)
       
   305 +    {
       
   306 +      zlog_warn ("failed to set BPF dev to immediate mode");
       
   307 +    }
       
   308 +
       
   309 +#ifdef BIOCSSEESENT
       
   310 +  /*
       
   311 +   * We want to see only incoming packets
       
   312 +   */
       
   313 +  if (ioctl (fd, BIOCSSEESENT, (caddr_t) & false) < 0)
       
   314 +    {
       
   315 +      zlog_warn ("failed to set BPF dev to incoming only mode");
       
   316 +    }
       
   317 +#endif
       
   318 +
       
   319 +  /*
       
   320 +   * ...but all of them
       
   321 +   */
       
   322 +  if (ioctl (fd, BIOCPROMISC, (caddr_t) & true) < 0)
       
   323 +    {
       
   324 +      zlog_warn ("failed to set BPF dev to promiscuous mode");
       
   325 +    }
       
   326 +
       
   327 +  /*
       
   328 +   * If the buffer length is smaller than our mtu, lets try to increase it
       
   329 +   */
       
   330 +  if (blen < circuit->interface->mtu)
       
   331 +    {
       
   332 +      if (ioctl (fd, BIOCSBLEN, &circuit->interface->mtu) < 0)
       
   333 +	{
       
   334 +	  zlog_warn ("failed to set BPF buffer len (%u to %u)", blen,
       
   335 +		     circuit->interface->mtu);
       
   336 +	}
       
   337 +    }
       
   338 +
       
   339 +  /*
       
   340 +   * Set a timeout parameter - hope this helps select()
       
   341 +   */
       
   342 +  timeout.tv_sec = 600;
       
   343 +  timeout.tv_usec = 0;
       
   344 +  if (ioctl (fd, BIOCSRTIMEOUT, (caddr_t) & timeout) < 0)
       
   345 +    {
       
   346 +      zlog_warn ("failed to set BPF device timeout");
       
   347 +    }
       
   348 +
       
   349 +  /*
       
   350 +   * And set the filter
       
   351 +   */
       
   352 +  memset (&bpf_prog, 0, sizeof (struct bpf_program));
       
   353 +  bpf_prog.bf_len = 8;
       
   354 +  bpf_prog.bf_insns = &(llcfilter[0]);
       
   355 +  if (ioctl (fd, BIOCSETF, (caddr_t) & bpf_prog) < 0)
       
   356 +    {
       
   357 +      zlog_warn ("open_bpf_dev(): failed to install filter: %s",
       
   358 +		 safe_strerror (errno));
       
   359 +      return ISIS_WARNING;
       
   360 +    }
       
   361 +
       
   362 +  assert (fd > 0);
       
   363 +
       
   364 +  circuit->fd = fd;
       
   365 +
       
   366 +  return ISIS_OK;
       
   367 +}
       
   368 +
       
   369 +/*
       
   370 + * Create the socket and set the tx/rx funcs
       
   371 + */
       
   372 +int
       
   373 +isis_sock_init (struct isis_circuit *circuit)
       
   374 +{
       
   375 +  int retval = ISIS_OK;
       
   376 +
       
   377 +  if (isisd_privs.change (ZPRIVS_RAISE))
       
   378 +    zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno));
       
   379 +
       
   380 +  retval = open_bpf_dev (circuit);
       
   381 +
       
   382 +  if (retval != ISIS_OK)
       
   383 +    {
       
   384 +      zlog_warn ("%s: could not initialize the socket", __func__);
       
   385 +      goto end;
       
   386 +    }
       
   387 +
       
   388 +  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
       
   389 +    {
       
   390 +      circuit->tx = isis_send_pdu_bcast;
       
   391 +      circuit->rx = isis_recv_pdu_bcast;
       
   392 +    }
       
   393 +  else if (circuit->circ_type == CIRCUIT_T_P2P)
       
   394 +    {
       
   395 +      circuit->tx = isis_send_pdu_p2p;
       
   396 +      circuit->rx = isis_recv_pdu_p2p;
       
   397 +    }
       
   398 +  else
       
   399 +    {
       
   400 +      zlog_warn ("isis_sock_init(): unknown circuit type");
       
   401 +      retval = ISIS_WARNING;
       
   402 +      goto end;
       
   403 +    }
       
   404 +
       
   405 +end:
       
   406 +  if (isisd_privs.change (ZPRIVS_LOWER))
       
   407 +    zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno));
       
   408 +
       
   409 +  return retval;
       
   410 +}
       
   411 +
       
   412 +int
       
   413 +isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
       
   414 +{
       
   415 +  int bytesread = 0, bytestoread, offset, one = 1;
       
   416 +  struct bpf_hdr *bpf_hdr;
       
   417 +
       
   418 +  assert (circuit->fd > 0);
       
   419 +
       
   420 +  if (ioctl (circuit->fd, FIONREAD, (caddr_t) & bytestoread) < 0)
       
   421 +    {
       
   422 +      zlog_warn ("ioctl() FIONREAD failed: %s", safe_strerror (errno));
       
   423 +    }
       
   424 +
       
   425 +  if (bytestoread)
       
   426 +    {
       
   427 +      bytesread = read (circuit->fd, readbuff, readblen);
       
   428 +    }
       
   429 +  if (bytesread < 0)
       
   430 +    {
       
   431 +      zlog_warn ("isis_recv_pdu_bcast(): read() failed: %s",
       
   432 +		 safe_strerror (errno));
       
   433 +      return ISIS_WARNING;
       
   434 +    }
       
   435 +
       
   436 +  if (bytesread == 0)
       
   437 +    return ISIS_WARNING;
       
   438 +
       
   439 +  bpf_hdr = (struct bpf_hdr *) readbuff;
       
   440 +
       
   441 +  assert (bpf_hdr->bh_caplen == bpf_hdr->bh_datalen);
       
   442 +
       
   443 +  offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN;
       
   444 +
       
   445 +  /* then we lose the BPF, LLC and ethernet headers */
       
   446 +  stream_write (circuit->rcv_stream, readbuff + offset, 
       
   447 +                bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
       
   448 +  stream_set_getp (circuit->rcv_stream, 0);
       
   449 +
       
   450 +  memcpy (ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN,
       
   451 +	  ETHER_ADDR_LEN);
       
   452 +
       
   453 +  if (ioctl (circuit->fd, BIOCFLUSH, &one) < 0)
       
   454 +    zlog_warn ("Flushing failed: %s", safe_strerror (errno));
       
   455 +
       
   456 +  return ISIS_OK;
       
   457 +}
       
   458 +
       
   459 +int
       
   460 +isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
       
   461 +{
       
   462 +  int bytesread;
       
   463 +
       
   464 +  bytesread = stream_read (circuit->rcv_stream, circuit->fd, 
       
   465 +                           circuit->interface->mtu);
       
   466 +
       
   467 +  if (bytesread < 0)
       
   468 +    {
       
   469 +      zlog_warn ("isis_recv_pdu_p2p(): read () failed: %s", safe_strerror (errno));
       
   470 +      return ISIS_WARNING;
       
   471 +    }
       
   472 +
       
   473 +  return ISIS_OK;
       
   474 +}
       
   475 +
       
   476 +int
       
   477 +isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
       
   478 +{
       
   479 +  struct ether_header *eth;
       
   480 +  int written;
       
   481 +
       
   482 +  stream_set_getp (circuit->snd_stream, 0);
       
   483 +
       
   484 +  /*
       
   485 +   * First the eth header
       
   486 +   */
       
   487 +  eth = (struct ether_header *) sock_buff;
       
   488 +  if (level == 1)
       
   489 +    memcpy (eth->ether_dhost, ALL_L1_ISS, ETHER_ADDR_LEN);
       
   490 +  else
       
   491 +    memcpy (eth->ether_dhost, ALL_L2_ISS, ETHER_ADDR_LEN);
       
   492 +  memcpy (eth->ether_shost, circuit->u.bc.snpa, ETHER_ADDR_LEN);
       
   493 +  eth->ether_type = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
       
   494 +
       
   495 +  /*
       
   496 +   * Then the LLC
       
   497 +   */
       
   498 +  sock_buff[ETHER_HDR_LEN] = ISO_SAP;
       
   499 +  sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP;
       
   500 +  sock_buff[ETHER_HDR_LEN + 2] = 0x03;
       
   501 +
       
   502 +  /* then we copy the data */
       
   503 +  memcpy (sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data,
       
   504 +	  stream_get_endp (circuit->snd_stream));
       
   505 +
       
   506 +  /* now we can send this */
       
   507 +  written = write (circuit->fd, sock_buff,
       
   508 +		   stream_get_endp (circuit->snd_stream) 
       
   509 +		    + LLC_LEN + ETHER_HDR_LEN);
       
   510 +
       
   511 +  return ISIS_OK;
       
   512 +}
       
   513 +
       
   514 +int
       
   515 +isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
       
   516 +{
       
   517 +  return ISIS_OK;
       
   518 +}
       
   519 diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
       
   520 index fe3eb82..af24988 100644
       
   521 --- isisd/isis_circuit.c
       
   522 +++ isisd/isis_circuit.c
       
   523 @@ -26,6 +26,10 @@
       
   524  #include <netinet/if_ether.h>
       
   525  #endif
       
   526  
       
   527 +#ifndef ETHER_ADDR_LEN
       
   528 +#define	ETHER_ADDR_LEN	ETHERADDRL
       
   529 +#endif
       
   530 +
       
   531  #include "log.h"
       
   532  #include "memory.h"
       
   533  #include "if.h"
       
   534 @@ -381,11 +385,13 @@ isis_circuit_if_add (struct isis_circuit *circuit, struct interface *ifp)
       
   535         * Get the Hardware Address
       
   536         */
       
   537  #ifdef HAVE_STRUCT_SOCKADDR_DL
       
   538 +#ifndef SUNOS_5
       
   539        if (circuit->interface->sdl.sdl_alen != ETHER_ADDR_LEN)
       
   540  	zlog_warn ("unsupported link layer");
       
   541        else
       
   542  	memcpy (circuit->u.bc.snpa, LLADDR (&circuit->interface->sdl),
       
   543  		ETH_ALEN);
       
   544 +#endif
       
   545  #else
       
   546        if (circuit->interface->hw_addr_len != ETH_ALEN)
       
   547  	{
       
   548 @@ -447,10 +453,12 @@ isis_circuit_update_params (struct isis_circuit *circuit,
       
   549     * Get the Hardware Address
       
   550     */
       
   551  #ifdef HAVE_STRUCT_SOCKADDR_DL
       
   552 +#ifndef SUNOS_5
       
   553    if (circuit->interface->sdl.sdl_alen != ETHER_ADDR_LEN)
       
   554      zlog_warn ("unsupported link layer");
       
   555    else
       
   556      memcpy (circuit->u.bc.snpa, LLADDR (&circuit->interface->sdl), ETH_ALEN);
       
   557 +#endif
       
   558  #else
       
   559    if (circuit->interface->hw_addr_len != ETH_ALEN)
       
   560      {
       
   561 diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
       
   562 index b5ef269..a7e719f 100644
       
   563 --- isisd/isis_circuit.h
       
   564 +++ isisd/isis_circuit.h
       
   565 @@ -69,6 +69,7 @@ struct isis_circuit
       
   566    struct isis_area *area;	/* back pointer to the area */
       
   567    struct interface *interface;	/* interface info from z */
       
   568    int fd;			/* IS-IS l1/2 socket */
       
   569 +  int sap_length;		/* SAP length for DLPI */
       
   570    struct nlpids nlpids;
       
   571    /*
       
   572     * Threads
       
   573 diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c
       
   574 new file mode 100644
       
   575 index 0000000..db4383b
       
   576 --- /dev/null
       
   577 +++ isisd/isis_dlpi.c
       
   578 @@ -0,0 +1,607 @@
       
   579 +/*
       
   580 + * IS-IS Rout(e)ing protocol - isis_dlpi.c
       
   581 + *
       
   582 + * Copyright (C) 2001,2002    Sampo Saaristo
       
   583 + *                            Tampere University of Technology      
       
   584 + *                            Institute of Communications Engineering
       
   585 + *
       
   586 + * This program is free software; you can redistribute it and/or modify it 
       
   587 + * under the terms of the GNU General Public Licenseas published by the Free 
       
   588 + * Software Foundation; either version 2 of the License, or (at your option) 
       
   589 + * any later version.
       
   590 + *
       
   591 + * This program is distributed in the hope that it will be useful,but WITHOUT 
       
   592 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
       
   593 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
       
   594 + * more details.
       
   595 +
       
   596 + * You should have received a copy of the GNU General Public License along 
       
   597 + * with this program; if not, write to the Free Software Foundation, Inc., 
       
   598 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
       
   599 + */
       
   600 +
       
   601 +#include <zebra.h>
       
   602 +#include <net/if.h>
       
   603 +#include <netinet/if_ether.h>
       
   604 +#include <sys/types.h>
       
   605 +#include <unistd.h>
       
   606 +#include <fcntl.h>
       
   607 +#include <stropts.h>
       
   608 +#include <poll.h>
       
   609 +#include <sys/dlpi.h>
       
   610 +#include <sys/pfmod.h>
       
   611 +
       
   612 +#include "log.h"
       
   613 +#include "stream.h"
       
   614 +#include "if.h"
       
   615 +
       
   616 +#include "isisd/dict.h"
       
   617 +#include "isisd/include-netbsd/iso.h"
       
   618 +#include "isisd/isis_constants.h"
       
   619 +#include "isisd/isis_common.h"
       
   620 +#include "isisd/isis_circuit.h"
       
   621 +#include "isisd/isis_flags.h"
       
   622 +#include "isisd/isisd.h"
       
   623 +#include "isisd/isis_constants.h"
       
   624 +#include "isisd/isis_circuit.h"
       
   625 +#include "isisd/isis_network.h"
       
   626 +
       
   627 +#include "privs.h"
       
   628 +
       
   629 +extern struct zebra_privs_t isisd_privs;
       
   630 +
       
   631 +static t_uscalar_t dlpi_ctl[1024];	/* DLPI control messages */
       
   632 +
       
   633 +/*
       
   634 + * Table 9 - Architectural constants for use with ISO 8802 subnetworks
       
   635 + * ISO 10589 - 8.4.8
       
   636 + */
       
   637 +
       
   638 +u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 };
       
   639 +u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 };
       
   640 +u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 };
       
   641 +u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 };
       
   642 +
       
   643 +static u_char sock_buff[8192];
       
   644 +
       
   645 +static u_short pf_filter[] =
       
   646 +{
       
   647 +  ENF_PUSHWORD + 0,		/* Get the SSAP/DSAP values */
       
   648 +  ENF_PUSHLIT | ENF_CAND,	/* Check them */
       
   649 +  ISO_SAP | (ISO_SAP << 8),
       
   650 +  ENF_PUSHWORD + 1,		/* Get the control value */
       
   651 +  ENF_PUSHLIT | ENF_AND,	/* Isolate it */
       
   652 +#ifdef _BIG_ENDIAN
       
   653 +  0xFF00,
       
   654 +#else
       
   655 +  0x00FF,
       
   656 +#endif
       
   657 +  ENF_PUSHLIT | ENF_CAND,	/* Test for expected value */
       
   658 +#ifdef _BIG_ENDIAN
       
   659 +  0x0300
       
   660 +#else
       
   661 +  0x0003
       
   662 +#endif
       
   663 +};
       
   664 +
       
   665 +/*
       
   666 + * We would like to use something like libdlpi here, but that's not present on
       
   667 + * all versions of Solaris or on any non-Solaris system, so it's nowhere near
       
   668 + * as portable as we'd like.  Thus, we use the standards-conformant DLPI
       
   669 + * interfaces plus the (optional; not needed) Solaris packet filter module.
       
   670 + */
       
   671 +
       
   672 +static void
       
   673 +dlpisend (int fd, const void *cbuf, size_t cbuflen,
       
   674 +  const void *dbuf, size_t dbuflen, int flags)
       
   675 +{
       
   676 +  const struct strbuf *ctlptr = NULL;
       
   677 +  const struct strbuf *dataptr = NULL;
       
   678 +  struct strbuf ctlbuf, databuf;
       
   679 +
       
   680 +  if (cbuf != NULL)
       
   681 +    {
       
   682 +      memset (&ctlbuf, 0, sizeof (ctlbuf));
       
   683 +      ctlbuf.len = cbuflen;
       
   684 +      ctlbuf.buf = (void *)cbuf;
       
   685 +      ctlptr = &ctlbuf;
       
   686 +    }
       
   687 +
       
   688 +  if (dbuf != NULL)
       
   689 +    {
       
   690 +      memset (&databuf, 0, sizeof (databuf));
       
   691 +      databuf.len = dbuflen;
       
   692 +      databuf.buf = (void *)dbuf;
       
   693 +      dataptr = &databuf;
       
   694 +    }
       
   695 +
       
   696 +  /* We assume this doesn't happen often and isn't operationally significant */
       
   697 +  if (putmsg (fd, ctlptr, dataptr, flags) == -1)
       
   698 +    zlog_debug ("%s: putmsg: %s", __func__, safe_strerror (errno));
       
   699 +}
       
   700 +
       
   701 +static ssize_t
       
   702 +dlpirctl (int fd)
       
   703 +{
       
   704 +  struct pollfd fds[1];
       
   705 +  struct strbuf ctlbuf, databuf;
       
   706 +  int flags, retv;
       
   707 +
       
   708 +  do
       
   709 +    {
       
   710 +      /* Poll is used here in case the device doesn't speak DLPI correctly */
       
   711 +      memset (fds, 0, sizeof (fds));
       
   712 +      fds[0].fd = fd;
       
   713 +      fds[0].events = POLLIN | POLLPRI;
       
   714 +      if (poll (fds, 1, 1000) <= 0)
       
   715 +	return -1;
       
   716 +
       
   717 +      memset (&ctlbuf, 0, sizeof (ctlbuf));
       
   718 +      memset (&databuf, 0, sizeof (databuf));
       
   719 +      ctlbuf.maxlen = sizeof (dlpi_ctl);
       
   720 +      ctlbuf.buf = (void *)dlpi_ctl;
       
   721 +      databuf.maxlen = sizeof (sock_buff);
       
   722 +      databuf.buf = (void *)sock_buff;
       
   723 +      flags = 0;
       
   724 +      retv = getmsg (fd, &ctlbuf, &databuf, &flags);
       
   725 +
       
   726 +      if (retv < 0)
       
   727 +	return -1;
       
   728 +    }
       
   729 +  while (ctlbuf.len == 0);
       
   730 +
       
   731 +  if (!(retv & MORECTL))
       
   732 +    {
       
   733 +      while (retv & MOREDATA)
       
   734 +	{
       
   735 +	  flags = 0;
       
   736 +	  retv = getmsg (fd, NULL, &databuf, &flags);
       
   737 +	}
       
   738 +      return ctlbuf.len;
       
   739 +    }
       
   740 +
       
   741 +  while (retv & MORECTL)
       
   742 +    {
       
   743 +      flags = 0;
       
   744 +      retv = getmsg (fd, &ctlbuf, &databuf, &flags);
       
   745 +    }
       
   746 +  return -1;
       
   747 +}
       
   748 +
       
   749 +static int
       
   750 +dlpiok (int fd, t_uscalar_t oprim)
       
   751 +{
       
   752 +  int retv;
       
   753 +  dl_ok_ack_t *doa = (dl_ok_ack_t *)dlpi_ctl;
       
   754 +
       
   755 +  retv = dlpirctl (fd);
       
   756 +  if (retv < DL_OK_ACK_SIZE || doa->dl_primitive != DL_OK_ACK ||
       
   757 +    doa->dl_correct_primitive != oprim)
       
   758 +    {
       
   759 +      return -1;
       
   760 +    }
       
   761 +  else
       
   762 +    {
       
   763 +      return 0;
       
   764 +    }
       
   765 +}
       
   766 +
       
   767 +static int
       
   768 +dlpiinfo (int fd)
       
   769 +{
       
   770 +  dl_info_req_t dir;
       
   771 +  ssize_t retv;
       
   772 +
       
   773 +  memset (&dir, 0, sizeof (dir));
       
   774 +  dir.dl_primitive = DL_INFO_REQ;
       
   775 +  /* Info_req uses M_PCPROTO. */
       
   776 +  dlpisend (fd, &dir, sizeof (dir), NULL, 0, RS_HIPRI);
       
   777 +  retv = dlpirctl (fd);
       
   778 +  if (retv < DL_INFO_ACK_SIZE || dlpi_ctl[0] != DL_INFO_ACK)
       
   779 +    return -1;
       
   780 +  else
       
   781 +    return retv;
       
   782 +}
       
   783 +
       
   784 +static int
       
   785 +dlpiopen (const char *devpath, ssize_t *acklen)
       
   786 +{
       
   787 +  int fd, flags;
       
   788 +
       
   789 +  fd = open (devpath, O_RDWR | O_NONBLOCK | O_NOCTTY);
       
   790 +  if (fd == -1)
       
   791 +    return -1;
       
   792 +
       
   793 +  /* All that we want is for the open itself to be non-blocking, not I/O. */
       
   794 +  flags = fcntl (fd, F_GETFL, 0);
       
   795 +  if (flags != -1)
       
   796 +    fcntl (fd, F_SETFL, flags & ~O_NONBLOCK);
       
   797 +
       
   798 +  /* After opening, ask for information */
       
   799 +  if ((*acklen = dlpiinfo (fd)) == -1)
       
   800 +    {
       
   801 +      close (fd);
       
   802 +      return -1;
       
   803 +    }
       
   804 +
       
   805 +  return fd;
       
   806 +}
       
   807 +
       
   808 +static int
       
   809 +dlpiattach (int fd, int unit)
       
   810 +{
       
   811 +  dl_attach_req_t dar;
       
   812 +
       
   813 +  memset (&dar, 0, sizeof (dar));
       
   814 +  dar.dl_primitive = DL_ATTACH_REQ;
       
   815 +  dar.dl_ppa = unit;
       
   816 +  dlpisend (fd, &dar, sizeof (dar), NULL, 0, 0);
       
   817 +  return dlpiok (fd, dar.dl_primitive);
       
   818 +}
       
   819 +
       
   820 +static int
       
   821 +dlpibind (int fd)
       
   822 +{
       
   823 +  dl_bind_req_t dbr;
       
   824 +  int retv;
       
   825 +  dl_bind_ack_t *dba = (dl_bind_ack_t *)dlpi_ctl;
       
   826 +
       
   827 +  memset (&dbr, 0, sizeof (dbr));
       
   828 +  dbr.dl_primitive = DL_BIND_REQ;
       
   829 +  dbr.dl_service_mode = DL_CLDLS;
       
   830 +  dlpisend (fd, &dbr, sizeof (dbr), NULL, 0, 0);
       
   831 +
       
   832 +  retv = dlpirctl (fd);
       
   833 +  if (retv < DL_BIND_ACK_SIZE || dba->dl_primitive != DL_BIND_ACK)
       
   834 +    return -1;
       
   835 +  else
       
   836 +    return 0;
       
   837 +}
       
   838 +
       
   839 +static int
       
   840 +dlpimcast (int fd, const u_char *mcaddr)
       
   841 +{
       
   842 +  struct {
       
   843 +    dl_enabmulti_req_t der;
       
   844 +    u_char addr[ETHERADDRL];
       
   845 +  } dler;
       
   846 +
       
   847 +  memset (&dler, 0, sizeof (dler));
       
   848 +  dler.der.dl_primitive = DL_ENABMULTI_REQ;
       
   849 +  dler.der.dl_addr_length = sizeof (dler.addr);
       
   850 +  dler.der.dl_addr_offset = dler.addr - (u_char *)&dler;
       
   851 +  memcpy (dler.addr, mcaddr, sizeof (dler.addr));
       
   852 +  dlpisend (fd, &dler, sizeof (dler), NULL, 0, 0);
       
   853 +  return dlpiok (fd, dler.der.dl_primitive);
       
   854 +}
       
   855 +
       
   856 +static int
       
   857 +dlpiaddr (int fd, u_char *addr)
       
   858 +{
       
   859 +  dl_phys_addr_req_t dpar;
       
   860 +  dl_phys_addr_ack_t *dpaa = (dl_phys_addr_ack_t *)dlpi_ctl;
       
   861 +  int retv;
       
   862 +
       
   863 +  memset (&dpar, 0, sizeof (dpar));
       
   864 +  dpar.dl_primitive = DL_PHYS_ADDR_REQ;
       
   865 +  dpar.dl_addr_type = DL_CURR_PHYS_ADDR;
       
   866 +  dlpisend (fd, &dpar, sizeof (dpar), NULL, 0, 0);
       
   867 +
       
   868 +  retv = dlpirctl (fd);
       
   869 +  if (retv < DL_PHYS_ADDR_ACK_SIZE || dpaa->dl_primitive != DL_PHYS_ADDR_ACK)
       
   870 +    return -1;
       
   871 +
       
   872 +  if (dpaa->dl_addr_offset < DL_PHYS_ADDR_ACK_SIZE ||
       
   873 +    dpaa->dl_addr_length != ETHERADDRL ||
       
   874 +    dpaa->dl_addr_offset + dpaa->dl_addr_length > retv)
       
   875 +    return -1;
       
   876 +
       
   877 +  bcopy((char *)dpaa + dpaa->dl_addr_offset, addr, ETHERADDRL);
       
   878 +  return 0;
       
   879 +}
       
   880 +
       
   881 +static int
       
   882 +open_dlpi_dev (struct isis_circuit *circuit)
       
   883 +{
       
   884 +  int fd, unit, retval;
       
   885 +  char devpath[MAXPATHLEN];
       
   886 +  dl_info_ack_t *dia = (dl_info_ack_t *)dlpi_ctl;
       
   887 +  ssize_t acklen;
       
   888 +
       
   889 +  /* Only broadcast-type are supported at the moment */
       
   890 +  if (circuit->circ_type != CIRCUIT_T_BROADCAST)
       
   891 +    {
       
   892 +      zlog_warn ("%s: non-broadcast interface %s", __func__,
       
   893 +	circuit->interface->name);
       
   894 +      return ISIS_WARNING;
       
   895 +    }
       
   896 +
       
   897 +  /* Try first as Style 1 */
       
   898 +  (void) snprintf(devpath, sizeof (devpath), "/dev/%s",
       
   899 +    circuit->interface->name);
       
   900 +  unit = -1;
       
   901 +  fd = dlpiopen (devpath, &acklen);
       
   902 +
       
   903 +  /* If that fails, try again as Style 2 */
       
   904 +  if (fd == -1)
       
   905 +    {
       
   906 +      char *cp;
       
   907 +
       
   908 +      cp = devpath + strlen (devpath);
       
   909 +      while (--cp >= devpath && isdigit(*cp))
       
   910 +	;
       
   911 +      unit = strtol(cp, NULL, 0);
       
   912 +      *cp = '\0';
       
   913 +      fd = dlpiopen (devpath, &acklen);
       
   914 +
       
   915 +      /* If that too fails, then the device really doesn't exist */
       
   916 +      if (fd == -1)
       
   917 +	{
       
   918 +	  zlog_warn ("%s: unknown interface %s", __func__,
       
   919 +	    circuit->interface->name);
       
   920 +	  return ISIS_WARNING;
       
   921 +	}
       
   922 +
       
   923 +      /* Double check the DLPI style */
       
   924 +      if (dia->dl_provider_style != DL_STYLE2)
       
   925 +	{
       
   926 +	  zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 2",
       
   927 +	    circuit->interface->name, devpath);
       
   928 +	  close (fd);
       
   929 +	  return ISIS_WARNING;
       
   930 +	}
       
   931 +
       
   932 +      /* If it succeeds, then we need to attach to the unit specified */
       
   933 +      dlpiattach (fd, unit);
       
   934 +
       
   935 +      /* Reget the information, as it may be different per node */
       
   936 +      if ((acklen = dlpiinfo (fd)) == -1)
       
   937 +	{
       
   938 +	  close (fd);
       
   939 +	  return ISIS_WARNING;
       
   940 +	}
       
   941 +    }
       
   942 +  else
       
   943 +    {
       
   944 +      /* Double check the DLPI style */
       
   945 +      if (dia->dl_provider_style != DL_STYLE1)
       
   946 +	{
       
   947 +	  zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 1",
       
   948 +	    circuit->interface->name, devpath);
       
   949 +	  close (fd);
       
   950 +	  return ISIS_WARNING;
       
   951 +	}
       
   952 +    }
       
   953 +
       
   954 +  /* Check that the interface we've got is the kind we expect */
       
   955 +  if ((dia->dl_sap_length != 2 && dia->dl_sap_length != -2) ||
       
   956 +    dia->dl_service_mode != DL_CLDLS || dia->dl_addr_length != ETHERADDRL + 2 ||
       
   957 +    dia->dl_brdcst_addr_length != ETHERADDRL)
       
   958 +    {
       
   959 +      zlog_warn ("%s: unsupported interface type for %s", __func__,
       
   960 +	circuit->interface->name);
       
   961 +      close (fd);
       
   962 +      return ISIS_WARNING;
       
   963 +    }
       
   964 +  switch (dia->dl_mac_type)
       
   965 +    {
       
   966 +    case DL_CSMACD:
       
   967 +    case DL_ETHER:
       
   968 +    case DL_100VG:
       
   969 +    case DL_100VGTPR:
       
   970 +    case DL_ETH_CSMA:
       
   971 +    case DL_100BT:
       
   972 +      break;
       
   973 +    default:
       
   974 +      zlog_warn ("%s: unexpected mac type on %s: %d", __func__,
       
   975 +	circuit->interface->name, dia->dl_mac_type);
       
   976 +      close (fd);
       
   977 +      return ISIS_WARNING;
       
   978 +    }
       
   979 +
       
   980 +  circuit->sap_length = dia->dl_sap_length;
       
   981 +
       
   982 +  /*
       
   983 +   * The local hardware address is something that should be provided by way of
       
   984 +   * sockaddr_dl for the interface, but isn't on Solaris.  We set it here based
       
   985 +   * on DLPI's reported address to avoid roto-tilling the world.
       
   986 +   * (Note that isis_circuit_if_add on Solaris doesn't set the snpa.)
       
   987 +   *
       
   988 +   * Unfortunately, GLD is broken and doesn't provide the address after attach,
       
   989 +   * so we need to be careful and use DL_PHYS_ADDR_REQ instead.
       
   990 +   */
       
   991 +  if (dlpiaddr (fd, circuit->u.bc.snpa) == -1)
       
   992 +    {
       
   993 +      zlog_warn ("open_dlpi_dev(): interface %s: unable to get MAC address",
       
   994 +	circuit->interface->name);
       
   995 +      close (fd);
       
   996 +      return ISIS_WARNING;
       
   997 +    }
       
   998 +
       
   999 +  /* Now bind to SAP 0.  This gives us 802-type traffic. */
       
  1000 +  if (dlpibind (fd) == -1)
       
  1001 +    {
       
  1002 +      zlog_warn ("%s: cannot bind SAP 0 on %s", __func__,
       
  1003 +	circuit->interface->name);
       
  1004 +      close (fd);
       
  1005 +      return ISIS_WARNING;
       
  1006 +    }
       
  1007 +
       
  1008 +  /*
       
  1009 +   * Join to multicast groups according to
       
  1010 +   * 8.4.2 - Broadcast subnetwork IIH PDUs
       
  1011 +   */
       
  1012 +  retval = 0;
       
  1013 +  if (circuit->circuit_is_type & IS_LEVEL_1)
       
  1014 +    {
       
  1015 +      retval |= dlpimcast (fd, ALL_L1_ISS);
       
  1016 +      retval |= dlpimcast (fd, ALL_ISS);
       
  1017 +    }
       
  1018 +  if (circuit->circuit_is_type & IS_LEVEL_2)
       
  1019 +    retval |= dlpimcast (fd, ALL_L2_ISS);
       
  1020 +
       
  1021 +  if (retval != 0)
       
  1022 +    {
       
  1023 +      zlog_warn ("%s: unable to join multicast on %s", __func__,
       
  1024 +	circuit->interface->name);
       
  1025 +      close (fd);
       
  1026 +      return ISIS_WARNING;
       
  1027 +    }
       
  1028 +
       
  1029 +  /* Push on the packet filter to avoid stray 802 packets */
       
  1030 +  if (ioctl (fd, I_PUSH, "pfmod") == 0)
       
  1031 +    {
       
  1032 +      struct packetfilt pfil;
       
  1033 +
       
  1034 +      pfil.Pf_Priority = 0;
       
  1035 +      pfil.Pf_FilterLen = sizeof (pf_filter) / sizeof (u_short);
       
  1036 +      memcpy (pfil.Pf_Filter, pf_filter, sizeof (pf_filter));
       
  1037 +      ioctl (fd, PFIOCSETF, &pfil);
       
  1038 +    }
       
  1039 +
       
  1040 +  circuit->fd = fd;
       
  1041 +
       
  1042 +  return ISIS_OK;
       
  1043 +}
       
  1044 +
       
  1045 +/*
       
  1046 + * Create the socket and set the tx/rx funcs
       
  1047 + */
       
  1048 +int
       
  1049 +isis_sock_init (struct isis_circuit *circuit)
       
  1050 +{
       
  1051 +  int retval = ISIS_OK;
       
  1052 +
       
  1053 +  if (isisd_privs.change (ZPRIVS_RAISE))
       
  1054 +    zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno));
       
  1055 +
       
  1056 +  retval = open_dlpi_dev (circuit);
       
  1057 +
       
  1058 +  if (retval != ISIS_OK)
       
  1059 +    {
       
  1060 +      zlog_warn ("%s: could not initialize the socket", __func__);
       
  1061 +      goto end;
       
  1062 +    }
       
  1063 +
       
  1064 +  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
       
  1065 +    {
       
  1066 +      circuit->tx = isis_send_pdu_bcast;
       
  1067 +      circuit->rx = isis_recv_pdu_bcast;
       
  1068 +    }
       
  1069 +  else
       
  1070 +    {
       
  1071 +      zlog_warn ("isis_sock_init(): unknown circuit type");
       
  1072 +      retval = ISIS_WARNING;
       
  1073 +      goto end;
       
  1074 +    }
       
  1075 +
       
  1076 +end:
       
  1077 +  if (isisd_privs.change (ZPRIVS_LOWER))
       
  1078 +    zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno));
       
  1079 +
       
  1080 +  return retval;
       
  1081 +}
       
  1082 +
       
  1083 +int
       
  1084 +isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
       
  1085 +{
       
  1086 +  struct pollfd fds[1];
       
  1087 +  struct strbuf ctlbuf, databuf;
       
  1088 +  int flags, retv;
       
  1089 +  dl_unitdata_ind_t *dui = (dl_unitdata_ind_t *)dlpi_ctl;
       
  1090 +
       
  1091 +  memset (fds, 0, sizeof (fds));
       
  1092 +  fds[0].fd = circuit->fd;
       
  1093 +  fds[0].events = POLLIN | POLLPRI;
       
  1094 +  if (poll (fds, 1, 0) <= 0)
       
  1095 +    return ISIS_WARNING;
       
  1096 +
       
  1097 +  memset (&ctlbuf, 0, sizeof (ctlbuf));
       
  1098 +  memset (&databuf, 0, sizeof (databuf));
       
  1099 +  ctlbuf.maxlen = sizeof (dlpi_ctl);
       
  1100 +  ctlbuf.buf = (void *)dlpi_ctl;
       
  1101 +  databuf.maxlen = sizeof (sock_buff);
       
  1102 +  databuf.buf = (void *)sock_buff;
       
  1103 +  flags = 0;
       
  1104 +  retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags);
       
  1105 +
       
  1106 +  if (retv < 0)
       
  1107 +    {
       
  1108 +      zlog_warn ("isis_recv_pdu_bcast: getmsg failed: %s",
       
  1109 +		 safe_strerror (errno));
       
  1110 +      return ISIS_WARNING;
       
  1111 +    }
       
  1112 +
       
  1113 +  if (retv & (MORECTL | MOREDATA))
       
  1114 +    {
       
  1115 +      while (retv & (MORECTL | MOREDATA))
       
  1116 +	{
       
  1117 +	  flags = 0;
       
  1118 +	  retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags);
       
  1119 +	}
       
  1120 +      return ISIS_WARNING;
       
  1121 +    }
       
  1122 +
       
  1123 +  if (ctlbuf.len < DL_UNITDATA_IND_SIZE ||
       
  1124 +    dui->dl_primitive != DL_UNITDATA_IND)
       
  1125 +    return ISIS_WARNING;
       
  1126 +
       
  1127 +  if (dui->dl_src_addr_length != ETHERADDRL + 2 ||
       
  1128 +    dui->dl_src_addr_offset < DL_UNITDATA_IND_SIZE ||
       
  1129 +    dui->dl_src_addr_offset + dui->dl_src_addr_length > ctlbuf.len)
       
  1130 +    return ISIS_WARNING;
       
  1131 +
       
  1132 +  memcpy (ssnpa, (char *)dui + dui->dl_src_addr_offset +
       
  1133 +    (circuit->sap_length > 0 ? circuit->sap_length : 0), ETHERADDRL);
       
  1134 +
       
  1135 +  if (databuf.len < LLC_LEN || sock_buff[0] != ISO_SAP ||
       
  1136 +    sock_buff[1] != ISO_SAP || sock_buff[2] != 3)
       
  1137 +    return ISIS_WARNING;
       
  1138 +
       
  1139 +  stream_write (circuit->rcv_stream, sock_buff + LLC_LEN,
       
  1140 +                databuf.len - LLC_LEN);
       
  1141 +  stream_set_getp (circuit->rcv_stream, 0);
       
  1142 +
       
  1143 +  return ISIS_OK;
       
  1144 +}
       
  1145 +
       
  1146 +int
       
  1147 +isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
       
  1148 +{
       
  1149 +  dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl;
       
  1150 +  char *dstaddr;
       
  1151 +  u_short *dstsap;
       
  1152 +
       
  1153 +  stream_set_getp (circuit->snd_stream, 0);
       
  1154 +
       
  1155 +  memset (dur, 0, sizeof (*dur));
       
  1156 +  dur->dl_primitive = DL_UNITDATA_REQ;
       
  1157 +  dur->dl_dest_addr_length = ETHERADDRL + 2;
       
  1158 +  dur->dl_dest_addr_offset = sizeof (*dur);
       
  1159 +
       
  1160 +  dstaddr = (char *)(dur + 1);
       
  1161 +  if (circuit->sap_length < 0)
       
  1162 +    {
       
  1163 +      dstsap = (u_short *)(dstaddr + ETHERADDRL);
       
  1164 +    }
       
  1165 +  else
       
  1166 +    {
       
  1167 +      dstsap = (u_short *)dstaddr;
       
  1168 +      dstaddr += circuit->sap_length;
       
  1169 +    }
       
  1170 +  if (level == 1)
       
  1171 +    memcpy (dstaddr, ALL_L1_ISS, ETHERADDRL);
       
  1172 +  else
       
  1173 +    memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL);
       
  1174 +  /* Note: DLPI SAP values are in host byte order */
       
  1175 +  *dstsap = stream_get_endp (circuit->snd_stream) + LLC_LEN;
       
  1176 +
       
  1177 +  sock_buff[0] = ISO_SAP;
       
  1178 +  sock_buff[1] = ISO_SAP;
       
  1179 +  sock_buff[2] = 0x03;
       
  1180 +  memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
       
  1181 +	  stream_get_endp (circuit->snd_stream));
       
  1182 +  dlpisend (circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length,
       
  1183 +    sock_buff, stream_get_endp (circuit->snd_stream) + LLC_LEN, 0);
       
  1184 +  return ISIS_OK;
       
  1185 +}
       
  1186 diff --git a/isisd/isis_flags.c b/isisd/isis_flags.c
       
  1187 index 1dd5493..859facd 100644
       
  1188 --- isisd/isis_flags.c
       
  1189 +++ isisd/isis_flags.c
       
  1190 @@ -29,6 +29,13 @@
       
  1191  #include "isisd/isis_common.h"
       
  1192  #include "isisd/isis_flags.h"
       
  1193  
       
  1194 +void
       
  1195 +flags_initialize (struct flags *flags)
       
  1196 +{
       
  1197 +  flags->maxindex = 0;
       
  1198 +  flags->free_idcs = NULL;
       
  1199 +}
       
  1200 +
       
  1201  int
       
  1202  flags_get_index (struct flags *flags)
       
  1203  {
       
  1204 @@ -37,8 +44,7 @@
       
  1205  
       
  1206    if (flags->free_idcs == NULL || flags->free_idcs->count == 0)
       
  1207      {
       
  1208 -      flags->maxindex++;
       
  1209 -      index = flags->maxindex;
       
  1210 +      index = flags->maxindex++;
       
  1211      }
       
  1212    else
       
  1213      {
       
  1214 @@ -45,6 +51,7 @@
       
  1215        node = listhead (flags->free_idcs);
       
  1216        index = (int) listgetdata (node);
       
  1217        listnode_delete (flags->free_idcs, (void *) index);
       
  1218 +      index--;
       
  1219      }
       
  1220  
       
  1221    return index;
       
  1222 @@ -53,12 +60,18 @@
       
  1223  void
       
  1224  flags_free_index (struct flags *flags, int index)
       
  1225  {
       
  1226 +  if (index + 1 == flags->maxindex)
       
  1227 +    {
       
  1228 +      flags->maxindex--;
       
  1229 +      return;
       
  1230 +    }
       
  1231 +
       
  1232    if (flags->free_idcs == NULL)
       
  1233      {
       
  1234        flags->free_idcs = list_new ();
       
  1235      }
       
  1236  
       
  1237 -  listnode_add (flags->free_idcs, (void *) index);
       
  1238 +  listnode_add (flags->free_idcs, (void *) (index + 1));
       
  1239  
       
  1240    return;
       
  1241  }
       
  1242 diff --git a/isisd/isis_flags.h b/isisd/isis_flags.h
       
  1243 --- isisd/isis_flags.h
       
  1244 +++ isisd/isis_flags.h
       
  1245 index 1dd5493..859facd 100644
       
  1246 @@ -28,6 +28,7 @@
       
  1247   * the support will be achived using the newest drafts */
       
  1248  #define ISIS_MAX_CIRCUITS 32 /* = 1024 */	/*FIXME:defined in lsp.h as well */
       
  1249  
       
  1250 +void flags_initialize (struct flags *flags);
       
  1251  struct flags *new_flags (int size);
       
  1252  int flags_get_index (struct flags *flags);
       
  1253  void flags_free_index (struct flags *flags, int index);
       
  1254 diff --git a/isisd/isis_network.c b/isisd/isis_network.c
       
  1255 deleted file mode 100644
       
  1256 index 56459ec..0000000
       
  1257 --- isisd/isis_network.c
       
  1258 +++ /dev/null
       
  1259 @@ -1,643 +0,0 @@
       
  1260 -/*
       
  1261 - * IS-IS Rout(e)ing protocol - isis_network.c   
       
  1262 - *
       
  1263 - * Copyright (C) 2001,2002    Sampo Saaristo
       
  1264 - *                            Tampere University of Technology      
       
  1265 - *                            Institute of Communications Engineering
       
  1266 - *
       
  1267 - * This program is free software; you can redistribute it and/or modify it 
       
  1268 - * under the terms of the GNU General Public Licenseas published by the Free 
       
  1269 - * Software Foundation; either version 2 of the License, or (at your option) 
       
  1270 - * any later version.
       
  1271 - *
       
  1272 - * This program is distributed in the hope that it will be useful,but WITHOUT 
       
  1273 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
       
  1274 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
       
  1275 - * more details.
       
  1276 -
       
  1277 - * You should have received a copy of the GNU General Public License along 
       
  1278 - * with this program; if not, write to the Free Software Foundation, Inc., 
       
  1279 - * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
       
  1280 - */
       
  1281 -
       
  1282 -#include <zebra.h>
       
  1283 -#ifdef GNU_LINUX
       
  1284 -#include <net/ethernet.h>	/* the L2 protocols */
       
  1285 -#else
       
  1286 -#include <net/if.h>
       
  1287 -#include <netinet/if_ether.h>
       
  1288 -#endif
       
  1289 -
       
  1290 -#include "log.h"
       
  1291 -#include "stream.h"
       
  1292 -#include "if.h"
       
  1293 -
       
  1294 -#include "isisd/dict.h"
       
  1295 -#include "isisd/include-netbsd/iso.h"
       
  1296 -#include "isisd/isis_constants.h"
       
  1297 -#include "isisd/isis_common.h"
       
  1298 -#include "isisd/isis_circuit.h"
       
  1299 -#include "isisd/isis_flags.h"
       
  1300 -#include "isisd/isisd.h"
       
  1301 -#include "isisd/isis_constants.h"
       
  1302 -#include "isisd/isis_circuit.h"
       
  1303 -#include "isisd/isis_network.h"
       
  1304 -
       
  1305 -#include "privs.h"
       
  1306 -
       
  1307 -extern struct zebra_privs_t isisd_privs;
       
  1308 -
       
  1309 -/*
       
  1310 - * On linux we can use the packet(7) sockets, in other OSs we have to do with
       
  1311 - * Berkley Packet Filter (BPF). Please tell me if you can think of a better 
       
  1312 - * way...
       
  1313 - */
       
  1314 -#ifdef GNU_LINUX
       
  1315 -#include <netpacket/packet.h>
       
  1316 -#else
       
  1317 -#include <sys/time.h>
       
  1318 -#include <sys/ioctl.h>
       
  1319 -#include <net/bpf.h>
       
  1320 -struct bpf_insn llcfilter[] = {
       
  1321 -  BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN),	/* check first byte */
       
  1322 -  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5),
       
  1323 -  BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1),
       
  1324 -  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3),	/* check second byte */
       
  1325 -  BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2),
       
  1326 -  BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1),	/* check third byte */
       
  1327 -  BPF_STMT (BPF_RET + BPF_K, (u_int) - 1),
       
  1328 -  BPF_STMT (BPF_RET + BPF_K, 0)
       
  1329 -};
       
  1330 -int readblen = 0;
       
  1331 -u_char *readbuff = NULL;
       
  1332 -#endif /* GNU_LINUX */
       
  1333 -
       
  1334 -/*
       
  1335 - * Table 9 - Architectural constans for use with ISO 8802 subnetworks
       
  1336 - * ISO 10589 - 8.4.8
       
  1337 - */
       
  1338 -
       
  1339 -u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 };
       
  1340 -u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 };
       
  1341 -u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 };
       
  1342 -u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 };
       
  1343 -
       
  1344 -#ifdef GNU_LINUX
       
  1345 -static char discard_buff[8192];
       
  1346 -#endif
       
  1347 -static char sock_buff[8192];
       
  1348 -
       
  1349 -/*
       
  1350 - * if level is 0 we are joining p2p multicast
       
  1351 - * FIXME: and the p2p multicast being ???
       
  1352 - */
       
  1353 -#ifdef GNU_LINUX
       
  1354 -static int
       
  1355 -isis_multicast_join (int fd, int registerto, int if_num)
       
  1356 -{
       
  1357 -  struct packet_mreq mreq;
       
  1358 -
       
  1359 -  memset (&mreq, 0, sizeof (mreq));
       
  1360 -  mreq.mr_ifindex = if_num;
       
  1361 -  if (registerto)
       
  1362 -    {
       
  1363 -      mreq.mr_type = PACKET_MR_MULTICAST;
       
  1364 -      mreq.mr_alen = ETH_ALEN;
       
  1365 -      if (registerto == 1)
       
  1366 -	memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN);
       
  1367 -      else if (registerto == 2)
       
  1368 -	memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN);
       
  1369 -      else if (registerto == 3)
       
  1370 -	memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN);
       
  1371 -      else
       
  1372 -	memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN);
       
  1373 -
       
  1374 -    }
       
  1375 -  else
       
  1376 -    {
       
  1377 -      mreq.mr_type = PACKET_MR_ALLMULTI;
       
  1378 -    }
       
  1379 -#ifdef EXTREME_DEBUG
       
  1380 -  zlog_debug ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, "
       
  1381 -	      "address = %02x:%02x:%02x:%02x:%02x:%02x",
       
  1382 -	      fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1],
       
  1383 -	      mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4],
       
  1384 -	      mreq.mr_address[5]);
       
  1385 -#endif /* EXTREME_DEBUG */
       
  1386 -  if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
       
  1387 -		  sizeof (struct packet_mreq)))
       
  1388 -    {
       
  1389 -      zlog_warn ("isis_multicast_join(): setsockopt(): %s", safe_strerror (errno));
       
  1390 -      return ISIS_WARNING;
       
  1391 -    }
       
  1392 -
       
  1393 -  return ISIS_OK;
       
  1394 -}
       
  1395 -
       
  1396 -static int
       
  1397 -open_packet_socket (struct isis_circuit *circuit)
       
  1398 -{
       
  1399 -  struct sockaddr_ll s_addr;
       
  1400 -  int fd, retval = ISIS_OK;
       
  1401 -
       
  1402 -  fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL));
       
  1403 -  if (fd < 0)
       
  1404 -    {
       
  1405 -      zlog_warn ("open_packet_socket(): socket() failed %s",
       
  1406 -		 safe_strerror (errno));
       
  1407 -      return ISIS_WARNING;
       
  1408 -    }
       
  1409 -
       
  1410 -  /*
       
  1411 -   * Bind to the physical interface
       
  1412 -   */
       
  1413 -  memset (&s_addr, 0, sizeof (struct sockaddr_ll));
       
  1414 -  s_addr.sll_family = AF_PACKET;
       
  1415 -  s_addr.sll_protocol = htons (ETH_P_ALL);
       
  1416 -  s_addr.sll_ifindex = circuit->interface->ifindex;
       
  1417 -
       
  1418 -  if (bind (fd, (struct sockaddr *) (&s_addr),
       
  1419 -	    sizeof (struct sockaddr_ll)) < 0)
       
  1420 -    {
       
  1421 -      zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno));
       
  1422 -      return ISIS_WARNING;
       
  1423 -    }
       
  1424 -
       
  1425 -  circuit->fd = fd;
       
  1426 -
       
  1427 -  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
       
  1428 -    {
       
  1429 -      /*
       
  1430 -       * Join to multicast groups
       
  1431 -       * according to
       
  1432 -       * 8.4.2 - Broadcast subnetwork IIH PDUs
       
  1433 -       * FIXME: is there a case only one will fail??
       
  1434 -       */
       
  1435 -      if (circuit->circuit_is_type & IS_LEVEL_1)
       
  1436 -	{
       
  1437 -	  /* joining ALL_L1_ISS */
       
  1438 -	  retval = isis_multicast_join (circuit->fd, 1,
       
  1439 -					circuit->interface->ifindex);
       
  1440 -	  /* joining ALL_ISS */
       
  1441 -	  retval = isis_multicast_join (circuit->fd, 3,
       
  1442 -					circuit->interface->ifindex);
       
  1443 -	}
       
  1444 -      if (circuit->circuit_is_type & IS_LEVEL_2)
       
  1445 -	/* joining ALL_L2_ISS */
       
  1446 -	retval = isis_multicast_join (circuit->fd, 2,
       
  1447 -				      circuit->interface->ifindex);
       
  1448 -    }
       
  1449 -  else
       
  1450 -    {
       
  1451 -      retval =
       
  1452 -	isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
       
  1453 -    }
       
  1454 -
       
  1455 -  return retval;
       
  1456 -}
       
  1457 -
       
  1458 -#else
       
  1459 -
       
  1460 -static int
       
  1461 -open_bpf_dev (struct isis_circuit *circuit)
       
  1462 -{
       
  1463 -  int i = 0, fd;
       
  1464 -  char bpfdev[128];
       
  1465 -  struct ifreq ifr;
       
  1466 -  u_int16_t blen;
       
  1467 -  int true = 1, false = 0;
       
  1468 -  struct timeval timeout;
       
  1469 -  struct bpf_program bpf_prog;
       
  1470 -
       
  1471 -  do
       
  1472 -    {
       
  1473 -      (void) snprintf (bpfdev, sizeof (bpfdev), "/dev/bpf%d", i++);
       
  1474 -      fd = open (bpfdev, O_RDWR);
       
  1475 -    }
       
  1476 -  while (fd < 0 && errno == EBUSY);
       
  1477 -
       
  1478 -  if (fd < 0)
       
  1479 -    {
       
  1480 -      zlog_warn ("open_bpf_dev(): failed to create bpf socket: %s",
       
  1481 -		 safe_strerror (errno));
       
  1482 -      return ISIS_WARNING;
       
  1483 -    }
       
  1484 -
       
  1485 -  zlog_debug ("Opened BPF device %s", bpfdev);
       
  1486 -
       
  1487 -  memcpy (ifr.ifr_name, circuit->interface->name, sizeof (ifr.ifr_name));
       
  1488 -  if (ioctl (fd, BIOCSETIF, (caddr_t) & ifr) < 0)
       
  1489 -    {
       
  1490 -      zlog_warn ("open_bpf_dev(): failed to bind to interface: %s",
       
  1491 -		 safe_strerror (errno));
       
  1492 -      return ISIS_WARNING;
       
  1493 -    }
       
  1494 -
       
  1495 -  if (ioctl (fd, BIOCGBLEN, (caddr_t) & blen) < 0)
       
  1496 -    {
       
  1497 -      zlog_warn ("failed to get BPF buffer len");
       
  1498 -      blen = circuit->interface->mtu;
       
  1499 -    }
       
  1500 -
       
  1501 -  readblen = blen;
       
  1502 -
       
  1503 -  if (readbuff == NULL)
       
  1504 -    readbuff = malloc (blen);
       
  1505 -
       
  1506 -  zlog_debug ("BPF buffer len = %u", blen);
       
  1507 -
       
  1508 -  /*  BPF(4): reads return immediately upon packet reception.
       
  1509 -   *  Otherwise, a read will block until either the kernel
       
  1510 -   *  buffer becomes full or a timeout occurs. 
       
  1511 -   */
       
  1512 -  if (ioctl (fd, BIOCIMMEDIATE, (caddr_t) & true) < 0)
       
  1513 -    {
       
  1514 -      zlog_warn ("failed to set BPF dev to immediate mode");
       
  1515 -    }
       
  1516 -
       
  1517 -#ifdef BIOCSSEESENT
       
  1518 -  /*
       
  1519 -   * We want to see only incoming packets
       
  1520 -   */
       
  1521 -  if (ioctl (fd, BIOCSSEESENT, (caddr_t) & false) < 0)
       
  1522 -    {
       
  1523 -      zlog_warn ("failed to set BPF dev to incoming only mode");
       
  1524 -    }
       
  1525 -#endif
       
  1526 -
       
  1527 -  /*
       
  1528 -   * ...but all of them
       
  1529 -   */
       
  1530 -  if (ioctl (fd, BIOCPROMISC, (caddr_t) & true) < 0)
       
  1531 -    {
       
  1532 -      zlog_warn ("failed to set BPF dev to promiscuous mode");
       
  1533 -    }
       
  1534 -
       
  1535 -  /*
       
  1536 -   * If the buffer length is smaller than our mtu, lets try to increase it
       
  1537 -   */
       
  1538 -  if (blen < circuit->interface->mtu)
       
  1539 -    {
       
  1540 -      if (ioctl (fd, BIOCSBLEN, &circuit->interface->mtu) < 0)
       
  1541 -	{
       
  1542 -	  zlog_warn ("failed to set BPF buffer len (%u to %u)", blen,
       
  1543 -		     circuit->interface->mtu);
       
  1544 -	}
       
  1545 -    }
       
  1546 -
       
  1547 -  /*
       
  1548 -   * Set a timeout parameter - hope this helps select()
       
  1549 -   */
       
  1550 -  timeout.tv_sec = 600;
       
  1551 -  timeout.tv_usec = 0;
       
  1552 -  if (ioctl (fd, BIOCSRTIMEOUT, (caddr_t) & timeout) < 0)
       
  1553 -    {
       
  1554 -      zlog_warn ("failed to set BPF device timeout");
       
  1555 -    }
       
  1556 -
       
  1557 -  /*
       
  1558 -   * And set the filter
       
  1559 -   */
       
  1560 -  memset (&bpf_prog, 0, sizeof (struct bpf_program));
       
  1561 -  bpf_prog.bf_len = 8;
       
  1562 -  bpf_prog.bf_insns = &(llcfilter[0]);
       
  1563 -  if (ioctl (fd, BIOCSETF, (caddr_t) & bpf_prog) < 0)
       
  1564 -    {
       
  1565 -      zlog_warn ("open_bpf_dev(): failed to install filter: %s",
       
  1566 -		 safe_strerror (errno));
       
  1567 -      return ISIS_WARNING;
       
  1568 -    }
       
  1569 -
       
  1570 -  assert (fd > 0);
       
  1571 -
       
  1572 -  circuit->fd = fd;
       
  1573 -
       
  1574 -  return ISIS_OK;
       
  1575 -}
       
  1576 -
       
  1577 -#endif /* GNU_LINUX */
       
  1578 -
       
  1579 -/*
       
  1580 - * Create the socket and set the tx/rx funcs
       
  1581 - */
       
  1582 -int
       
  1583 -isis_sock_init (struct isis_circuit *circuit)
       
  1584 -{
       
  1585 -  int retval = ISIS_OK;
       
  1586 -
       
  1587 -  if (isisd_privs.change (ZPRIVS_RAISE))
       
  1588 -    zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno));
       
  1589 -
       
  1590 -#ifdef GNU_LINUX
       
  1591 -  retval = open_packet_socket (circuit);
       
  1592 -#else
       
  1593 -  retval = open_bpf_dev (circuit);
       
  1594 -#endif
       
  1595 -
       
  1596 -  if (retval != ISIS_OK)
       
  1597 -    {
       
  1598 -      zlog_warn ("%s: could not initialize the socket", __func__);
       
  1599 -      goto end;
       
  1600 -    }
       
  1601 -
       
  1602 -  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
       
  1603 -    {
       
  1604 -      circuit->tx = isis_send_pdu_bcast;
       
  1605 -      circuit->rx = isis_recv_pdu_bcast;
       
  1606 -    }
       
  1607 -  else if (circuit->circ_type == CIRCUIT_T_P2P)
       
  1608 -    {
       
  1609 -      circuit->tx = isis_send_pdu_p2p;
       
  1610 -      circuit->rx = isis_recv_pdu_p2p;
       
  1611 -    }
       
  1612 -  else
       
  1613 -    {
       
  1614 -      zlog_warn ("isis_sock_init(): unknown circuit type");
       
  1615 -      retval = ISIS_WARNING;
       
  1616 -      goto end;
       
  1617 -    }
       
  1618 -
       
  1619 -end:
       
  1620 -  if (isisd_privs.change (ZPRIVS_LOWER))
       
  1621 -    zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno));
       
  1622 -
       
  1623 -  return retval;
       
  1624 -}
       
  1625 -
       
  1626 -static inline int
       
  1627 -llc_check (u_char * llc)
       
  1628 -{
       
  1629 -  if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3)
       
  1630 -    return 0;
       
  1631 -
       
  1632 -  return 1;
       
  1633 -}
       
  1634 -
       
  1635 -#ifdef GNU_LINUX
       
  1636 -int
       
  1637 -isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
       
  1638 -{
       
  1639 -  int bytesread, addr_len;
       
  1640 -  struct sockaddr_ll s_addr;
       
  1641 -  u_char llc[LLC_LEN];
       
  1642 -
       
  1643 -  addr_len = sizeof (s_addr);
       
  1644 -
       
  1645 -  memset (&s_addr, 0, sizeof (struct sockaddr_ll));
       
  1646 -
       
  1647 -  bytesread = recvfrom (circuit->fd, (void *) &llc,
       
  1648 -			LLC_LEN, MSG_PEEK,
       
  1649 -			(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
       
  1650 -
       
  1651 -  if (bytesread < 0)
       
  1652 -    {
       
  1653 -      zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s",
       
  1654 -		 circuit->fd, safe_strerror (errno));
       
  1655 -      zlog_warn ("circuit is %s", circuit->interface->name);
       
  1656 -      zlog_warn ("circuit fd %d", circuit->fd);
       
  1657 -      zlog_warn ("bytesread %d", bytesread);
       
  1658 -      /* get rid of the packet */
       
  1659 -      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
       
  1660 -      return ISIS_WARNING;
       
  1661 -    }
       
  1662 -  /*
       
  1663 -   * Filtering by llc field, discard packets sent by this host (other circuit)
       
  1664 -   */
       
  1665 -  if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING)
       
  1666 -    {
       
  1667 -      /*  Read the packet into discard buff */
       
  1668 -      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
       
  1669 -      if (bytesread < 0)
       
  1670 -	zlog_warn ("isis_recv_pdu_bcast(): read() failed");
       
  1671 -      return ISIS_WARNING;
       
  1672 -    }
       
  1673 -
       
  1674 -  /* on lan we have to read to the static buff first */
       
  1675 -  bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0,
       
  1676 -			(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
       
  1677 -
       
  1678 -  /* then we lose the LLC */
       
  1679 -  stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN);
       
  1680 -
       
  1681 -  memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen);
       
  1682 -
       
  1683 -  return ISIS_OK;
       
  1684 -}
       
  1685 -
       
  1686 -int
       
  1687 -isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
       
  1688 -{
       
  1689 -  int bytesread, addr_len;
       
  1690 -  struct sockaddr_ll s_addr;
       
  1691 -
       
  1692 -  memset (&s_addr, 0, sizeof (struct sockaddr_ll));
       
  1693 -  addr_len = sizeof (s_addr);
       
  1694 -
       
  1695 -  /* we can read directly to the stream */
       
  1696 -  bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd,
       
  1697 -                               circuit->interface->mtu, 0,
       
  1698 -                               (struct sockaddr *) &s_addr, 
       
  1699 -                               (socklen_t *) &addr_len);
       
  1700 -
       
  1701 -  if (s_addr.sll_pkttype == PACKET_OUTGOING)
       
  1702 -    {
       
  1703 -      /*  Read the packet into discard buff */
       
  1704 -      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
       
  1705 -      if (bytesread < 0)
       
  1706 -	zlog_warn ("isis_recv_pdu_p2p(): read() failed");
       
  1707 -      return ISIS_WARNING;
       
  1708 -    }
       
  1709 -
       
  1710 -  /* If we don't have protocol type 0x00FE which is
       
  1711 -   * ISO over GRE we exit with pain :)
       
  1712 -   */
       
  1713 -  if (ntohs (s_addr.sll_protocol) != 0x00FE)
       
  1714 -    {
       
  1715 -      zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X",
       
  1716 -		 ntohs (s_addr.sll_protocol));
       
  1717 -      return ISIS_WARNING;
       
  1718 -    }
       
  1719 -
       
  1720 -  memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen);
       
  1721 -
       
  1722 -  return ISIS_OK;
       
  1723 -}
       
  1724 -
       
  1725 -int
       
  1726 -isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
       
  1727 -{
       
  1728 -  /* we need to do the LLC in here because of P2P circuits, which will
       
  1729 -   * not need it
       
  1730 -   */
       
  1731 -  int written = 1;
       
  1732 -  struct sockaddr_ll sa;
       
  1733 -
       
  1734 -  stream_set_getp (circuit->snd_stream, 0);
       
  1735 -  memset (&sa, 0, sizeof (struct sockaddr_ll));
       
  1736 -  sa.sll_family = AF_PACKET;
       
  1737 -  sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
       
  1738 -  sa.sll_ifindex = circuit->interface->ifindex;
       
  1739 -  sa.sll_halen = ETH_ALEN;
       
  1740 -  if (level == 1)
       
  1741 -    memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
       
  1742 -  else
       
  1743 -    memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
       
  1744 -
       
  1745 -  /* on a broadcast circuit */
       
  1746 -  /* first we put the LLC in */
       
  1747 -  sock_buff[0] = 0xFE;
       
  1748 -  sock_buff[1] = 0xFE;
       
  1749 -  sock_buff[2] = 0x03;
       
  1750 -
       
  1751 -  /* then we copy the data */
       
  1752 -  memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
       
  1753 -	  stream_get_endp (circuit->snd_stream));
       
  1754 -
       
  1755 -  /* now we can send this */
       
  1756 -  written = sendto (circuit->fd, sock_buff,
       
  1757 -		    stream_get_endp(circuit->snd_stream) + LLC_LEN, 0,
       
  1758 -		    (struct sockaddr *) &sa, sizeof (struct sockaddr_ll));
       
  1759 -
       
  1760 -  return ISIS_OK;
       
  1761 -}
       
  1762 -
       
  1763 -int
       
  1764 -isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
       
  1765 -{
       
  1766 -
       
  1767 -  int written = 1;
       
  1768 -  struct sockaddr_ll sa;
       
  1769 -
       
  1770 -  stream_set_getp (circuit->snd_stream, 0);
       
  1771 -  memset (&sa, 0, sizeof (struct sockaddr_ll));
       
  1772 -  sa.sll_family = AF_PACKET;
       
  1773 -  sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
       
  1774 -  sa.sll_ifindex = circuit->interface->ifindex;
       
  1775 -  sa.sll_halen = ETH_ALEN;
       
  1776 -  if (level == 1)
       
  1777 -    memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
       
  1778 -  else
       
  1779 -    memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
       
  1780 -
       
  1781 -
       
  1782 -  /* lets try correcting the protocol */
       
  1783 -  sa.sll_protocol = htons (0x00FE);
       
  1784 -  written = sendto (circuit->fd, circuit->snd_stream->data,
       
  1785 -		    stream_get_endp (circuit->snd_stream), 0, 
       
  1786 -		    (struct sockaddr *) &sa,
       
  1787 -		    sizeof (struct sockaddr_ll));
       
  1788 -
       
  1789 -  return ISIS_OK;
       
  1790 -}
       
  1791 -
       
  1792 -#else
       
  1793 -
       
  1794 -int
       
  1795 -isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
       
  1796 -{
       
  1797 -  int bytesread = 0, bytestoread, offset, one = 1;
       
  1798 -  struct bpf_hdr *bpf_hdr;
       
  1799 -
       
  1800 -  assert (circuit->fd > 0);
       
  1801 -
       
  1802 -  if (ioctl (circuit->fd, FIONREAD, (caddr_t) & bytestoread) < 0)
       
  1803 -    {
       
  1804 -      zlog_warn ("ioctl() FIONREAD failed: %s", safe_strerror (errno));
       
  1805 -    }
       
  1806 -
       
  1807 -  if (bytestoread)
       
  1808 -    {
       
  1809 -      bytesread = read (circuit->fd, readbuff, readblen);
       
  1810 -    }
       
  1811 -  if (bytesread < 0)
       
  1812 -    {
       
  1813 -      zlog_warn ("isis_recv_pdu_bcast(): read() failed: %s",
       
  1814 -		 safe_strerror (errno));
       
  1815 -      return ISIS_WARNING;
       
  1816 -    }
       
  1817 -
       
  1818 -  if (bytesread == 0)
       
  1819 -    return ISIS_WARNING;
       
  1820 -
       
  1821 -  bpf_hdr = (struct bpf_hdr *) readbuff;
       
  1822 -
       
  1823 -  assert (bpf_hdr->bh_caplen == bpf_hdr->bh_datalen);
       
  1824 -
       
  1825 -  offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN;
       
  1826 -
       
  1827 -  /* then we lose the BPF, LLC and ethernet headers */
       
  1828 -  stream_write (circuit->rcv_stream, readbuff + offset, 
       
  1829 -                bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN);
       
  1830 -  stream_set_getp (circuit->rcv_stream, 0);
       
  1831 -
       
  1832 -  memcpy (ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETHER_ADDR_LEN,
       
  1833 -	  ETHER_ADDR_LEN);
       
  1834 -
       
  1835 -  if (ioctl (circuit->fd, BIOCFLUSH, &one) < 0)
       
  1836 -    zlog_warn ("Flushing failed: %s", safe_strerror (errno));
       
  1837 -
       
  1838 -  return ISIS_OK;
       
  1839 -}
       
  1840 -
       
  1841 -int
       
  1842 -isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
       
  1843 -{
       
  1844 -  int bytesread;
       
  1845 -
       
  1846 -  bytesread = stream_read (circuit->rcv_stream, circuit->fd, 
       
  1847 -                           circuit->interface->mtu);
       
  1848 -
       
  1849 -  if (bytesread < 0)
       
  1850 -    {
       
  1851 -      zlog_warn ("isis_recv_pdu_p2p(): read () failed: %s", safe_strerror (errno));
       
  1852 -      return ISIS_WARNING;
       
  1853 -    }
       
  1854 -
       
  1855 -  return ISIS_OK;
       
  1856 -}
       
  1857 -
       
  1858 -int
       
  1859 -isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
       
  1860 -{
       
  1861 -  struct ether_header *eth;
       
  1862 -  int written;
       
  1863 -
       
  1864 -  stream_set_getp (circuit->snd_stream, 0);
       
  1865 -
       
  1866 -  /*
       
  1867 -   * First the eth header
       
  1868 -   */
       
  1869 -  eth = (struct ether_header *) sock_buff;
       
  1870 -  if (level == 1)
       
  1871 -    memcpy (eth->ether_dhost, ALL_L1_ISS, ETHER_ADDR_LEN);
       
  1872 -  else
       
  1873 -    memcpy (eth->ether_dhost, ALL_L2_ISS, ETHER_ADDR_LEN);
       
  1874 -  memcpy (eth->ether_shost, circuit->u.bc.snpa, ETHER_ADDR_LEN);
       
  1875 -  eth->ether_type = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
       
  1876 -
       
  1877 -  /*
       
  1878 -   * Then the LLC
       
  1879 -   */
       
  1880 -  sock_buff[ETHER_HDR_LEN] = ISO_SAP;
       
  1881 -  sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP;
       
  1882 -  sock_buff[ETHER_HDR_LEN + 2] = 0x03;
       
  1883 -
       
  1884 -  /* then we copy the data */
       
  1885 -  memcpy (sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data,
       
  1886 -	  stream_get_endp (circuit->snd_stream));
       
  1887 -
       
  1888 -  /* now we can send this */
       
  1889 -  written = write (circuit->fd, sock_buff,
       
  1890 -		   stream_get_endp (circuit->snd_stream) 
       
  1891 -		    + LLC_LEN + ETHER_HDR_LEN);
       
  1892 -
       
  1893 -  return ISIS_OK;
       
  1894 -}
       
  1895 -
       
  1896 -int
       
  1897 -isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
       
  1898 -{
       
  1899 -  return ISIS_OK;
       
  1900 -}
       
  1901 -
       
  1902 -#endif /* GNU_LINUX */
       
  1903 diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h
       
  1904 index 29c7621..95c1ee4 100644
       
  1905 --- isisd/isis_pdu.h
       
  1906 +++ isisd/isis_pdu.h
       
  1907 @@ -24,6 +24,10 @@
       
  1908  #ifndef _ZEBRA_ISIS_PDU_H
       
  1909  #define _ZEBRA_ISIS_PDU_H
       
  1910  
       
  1911 +#ifdef __SUNPRO_C
       
  1912 +#pragma pack(1)
       
  1913 +#endif
       
  1914 +
       
  1915  /*
       
  1916   *                    ISO 9542 - 7.5,7.6
       
  1917   *
       
  1918 @@ -222,6 +226,10 @@ struct isis_partial_seqnum_hdr
       
  1919  };
       
  1920  #define ISIS_PSNP_HDRLEN 9
       
  1921  
       
  1922 +#ifdef __SUNPRO_C
       
  1923 +#pragma pack()
       
  1924 +#endif
       
  1925 +
       
  1926  /*
       
  1927   * Function for receiving IS-IS PDUs
       
  1928   */
       
  1929 diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c
       
  1930 new file mode 100644
       
  1931 index 0000000..8752dba
       
  1932 --- /dev/null
       
  1933 +++ isisd/isis_pfpacket.c
       
  1934 @@ -0,0 +1,373 @@
       
  1935 +/*
       
  1936 + * IS-IS Rout(e)ing protocol - isis_pfpacket.c
       
  1937 + *
       
  1938 + * Copyright (C) 2001,2002    Sampo Saaristo
       
  1939 + *                            Tampere University of Technology      
       
  1940 + *                            Institute of Communications Engineering
       
  1941 + *
       
  1942 + * This program is free software; you can redistribute it and/or modify it 
       
  1943 + * under the terms of the GNU General Public Licenseas published by the Free 
       
  1944 + * Software Foundation; either version 2 of the License, or (at your option) 
       
  1945 + * any later version.
       
  1946 + *
       
  1947 + * This program is distributed in the hope that it will be useful,but WITHOUT 
       
  1948 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
       
  1949 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
       
  1950 + * more details.
       
  1951 +
       
  1952 + * You should have received a copy of the GNU General Public License along 
       
  1953 + * with this program; if not, write to the Free Software Foundation, Inc., 
       
  1954 + * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
       
  1955 + */
       
  1956 +
       
  1957 +#include <zebra.h>
       
  1958 +#include <net/ethernet.h>	/* the L2 protocols */
       
  1959 +#include <netpacket/packet.h>
       
  1960 +
       
  1961 +#include "log.h"
       
  1962 +#include "stream.h"
       
  1963 +#include "if.h"
       
  1964 +
       
  1965 +#include "isisd/dict.h"
       
  1966 +#include "isisd/include-netbsd/iso.h"
       
  1967 +#include "isisd/isis_constants.h"
       
  1968 +#include "isisd/isis_common.h"
       
  1969 +#include "isisd/isis_circuit.h"
       
  1970 +#include "isisd/isis_flags.h"
       
  1971 +#include "isisd/isisd.h"
       
  1972 +#include "isisd/isis_constants.h"
       
  1973 +#include "isisd/isis_circuit.h"
       
  1974 +#include "isisd/isis_network.h"
       
  1975 +
       
  1976 +#include "privs.h"
       
  1977 +
       
  1978 +extern struct zebra_privs_t isisd_privs;
       
  1979 +
       
  1980 +/*
       
  1981 + * Table 9 - Architectural constants for use with ISO 8802 subnetworks
       
  1982 + * ISO 10589 - 8.4.8
       
  1983 + */
       
  1984 +
       
  1985 +u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 };
       
  1986 +u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 };
       
  1987 +u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 };
       
  1988 +u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 };
       
  1989 +
       
  1990 +static char discard_buff[8192];
       
  1991 +static char sock_buff[8192];
       
  1992 +
       
  1993 +/*
       
  1994 + * if level is 0 we are joining p2p multicast
       
  1995 + * FIXME: and the p2p multicast being ???
       
  1996 + */
       
  1997 +static int
       
  1998 +isis_multicast_join (int fd, int registerto, int if_num)
       
  1999 +{
       
  2000 +  struct packet_mreq mreq;
       
  2001 +
       
  2002 +  memset (&mreq, 0, sizeof (mreq));
       
  2003 +  mreq.mr_ifindex = if_num;
       
  2004 +  if (registerto)
       
  2005 +    {
       
  2006 +      mreq.mr_type = PACKET_MR_MULTICAST;
       
  2007 +      mreq.mr_alen = ETH_ALEN;
       
  2008 +      if (registerto == 1)
       
  2009 +	memcpy (&mreq.mr_address, ALL_L1_ISS, ETH_ALEN);
       
  2010 +      else if (registerto == 2)
       
  2011 +	memcpy (&mreq.mr_address, ALL_L2_ISS, ETH_ALEN);
       
  2012 +      else if (registerto == 3)
       
  2013 +	memcpy (&mreq.mr_address, ALL_ISS, ETH_ALEN);
       
  2014 +      else
       
  2015 +	memcpy (&mreq.mr_address, ALL_ESS, ETH_ALEN);
       
  2016 +
       
  2017 +    }
       
  2018 +  else
       
  2019 +    {
       
  2020 +      mreq.mr_type = PACKET_MR_ALLMULTI;
       
  2021 +    }
       
  2022 +#ifdef EXTREME_DEBUG
       
  2023 +  zlog_debug ("isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, "
       
  2024 +	      "address = %02x:%02x:%02x:%02x:%02x:%02x",
       
  2025 +	      fd, registerto, if_num, mreq.mr_address[0], mreq.mr_address[1],
       
  2026 +	      mreq.mr_address[2], mreq.mr_address[3], mreq.mr_address[4],
       
  2027 +	      mreq.mr_address[5]);
       
  2028 +#endif /* EXTREME_DEBUG */
       
  2029 +  if (setsockopt (fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
       
  2030 +		  sizeof (struct packet_mreq)))
       
  2031 +    {
       
  2032 +      zlog_warn ("isis_multicast_join(): setsockopt(): %s", safe_strerror (errno));
       
  2033 +      return ISIS_WARNING;
       
  2034 +    }
       
  2035 +
       
  2036 +  return ISIS_OK;
       
  2037 +}
       
  2038 +
       
  2039 +static int
       
  2040 +open_packet_socket (struct isis_circuit *circuit)
       
  2041 +{
       
  2042 +  struct sockaddr_ll s_addr;
       
  2043 +  int fd, retval = ISIS_OK;
       
  2044 +
       
  2045 +  fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL));
       
  2046 +  if (fd < 0)
       
  2047 +    {
       
  2048 +      zlog_warn ("open_packet_socket(): socket() failed %s",
       
  2049 +		 safe_strerror (errno));
       
  2050 +      return ISIS_WARNING;
       
  2051 +    }
       
  2052 +
       
  2053 +  /*
       
  2054 +   * Bind to the physical interface
       
  2055 +   */
       
  2056 +  memset (&s_addr, 0, sizeof (struct sockaddr_ll));
       
  2057 +  s_addr.sll_family = AF_PACKET;
       
  2058 +  s_addr.sll_protocol = htons (ETH_P_ALL);
       
  2059 +  s_addr.sll_ifindex = circuit->interface->ifindex;
       
  2060 +
       
  2061 +  if (bind (fd, (struct sockaddr *) (&s_addr),
       
  2062 +	    sizeof (struct sockaddr_ll)) < 0)
       
  2063 +    {
       
  2064 +      zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno));
       
  2065 +      return ISIS_WARNING;
       
  2066 +    }
       
  2067 +
       
  2068 +  circuit->fd = fd;
       
  2069 +
       
  2070 +  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
       
  2071 +    {
       
  2072 +      /*
       
  2073 +       * Join to multicast groups
       
  2074 +       * according to
       
  2075 +       * 8.4.2 - Broadcast subnetwork IIH PDUs
       
  2076 +       * FIXME: is there a case only one will fail??
       
  2077 +       */
       
  2078 +      if (circuit->circuit_is_type & IS_LEVEL_1)
       
  2079 +	{
       
  2080 +	  /* joining ALL_L1_ISS */
       
  2081 +	  retval = isis_multicast_join (circuit->fd, 1,
       
  2082 +					circuit->interface->ifindex);
       
  2083 +	  /* joining ALL_ISS */
       
  2084 +	  retval = isis_multicast_join (circuit->fd, 3,
       
  2085 +					circuit->interface->ifindex);
       
  2086 +	}
       
  2087 +      if (circuit->circuit_is_type & IS_LEVEL_2)
       
  2088 +	/* joining ALL_L2_ISS */
       
  2089 +	retval = isis_multicast_join (circuit->fd, 2,
       
  2090 +				      circuit->interface->ifindex);
       
  2091 +    }
       
  2092 +  else
       
  2093 +    {
       
  2094 +      retval =
       
  2095 +	isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
       
  2096 +    }
       
  2097 +
       
  2098 +  return retval;
       
  2099 +}
       
  2100 +
       
  2101 +/*
       
  2102 + * Create the socket and set the tx/rx funcs
       
  2103 + */
       
  2104 +int
       
  2105 +isis_sock_init (struct isis_circuit *circuit)
       
  2106 +{
       
  2107 +  int retval = ISIS_OK;
       
  2108 +
       
  2109 +  if (isisd_privs.change (ZPRIVS_RAISE))
       
  2110 +    zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno));
       
  2111 +
       
  2112 +  retval = open_packet_socket (circuit);
       
  2113 +
       
  2114 +  if (retval != ISIS_OK)
       
  2115 +    {
       
  2116 +      zlog_warn ("%s: could not initialize the socket", __func__);
       
  2117 +      goto end;
       
  2118 +    }
       
  2119 +
       
  2120 +  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
       
  2121 +    {
       
  2122 +      circuit->tx = isis_send_pdu_bcast;
       
  2123 +      circuit->rx = isis_recv_pdu_bcast;
       
  2124 +    }
       
  2125 +  else if (circuit->circ_type == CIRCUIT_T_P2P)
       
  2126 +    {
       
  2127 +      circuit->tx = isis_send_pdu_p2p;
       
  2128 +      circuit->rx = isis_recv_pdu_p2p;
       
  2129 +    }
       
  2130 +  else
       
  2131 +    {
       
  2132 +      zlog_warn ("isis_sock_init(): unknown circuit type");
       
  2133 +      retval = ISIS_WARNING;
       
  2134 +      goto end;
       
  2135 +    }
       
  2136 +
       
  2137 +end:
       
  2138 +  if (isisd_privs.change (ZPRIVS_LOWER))
       
  2139 +    zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno));
       
  2140 +
       
  2141 +  return retval;
       
  2142 +}
       
  2143 +
       
  2144 +static inline int
       
  2145 +llc_check (u_char * llc)
       
  2146 +{
       
  2147 +  if (*llc != ISO_SAP || *(llc + 1) != ISO_SAP || *(llc + 2) != 3)
       
  2148 +    return 0;
       
  2149 +
       
  2150 +  return 1;
       
  2151 +}
       
  2152 +
       
  2153 +int
       
  2154 +isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
       
  2155 +{
       
  2156 +  int bytesread, addr_len;
       
  2157 +  struct sockaddr_ll s_addr;
       
  2158 +  u_char llc[LLC_LEN];
       
  2159 +
       
  2160 +  addr_len = sizeof (s_addr);
       
  2161 +
       
  2162 +  memset (&s_addr, 0, sizeof (struct sockaddr_ll));
       
  2163 +
       
  2164 +  bytesread = recvfrom (circuit->fd, (void *) &llc,
       
  2165 +			LLC_LEN, MSG_PEEK,
       
  2166 +			(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
       
  2167 +
       
  2168 +  if (bytesread < 0)
       
  2169 +    {
       
  2170 +      zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s",
       
  2171 +		 circuit->fd, safe_strerror (errno));
       
  2172 +      zlog_warn ("circuit is %s", circuit->interface->name);
       
  2173 +      zlog_warn ("circuit fd %d", circuit->fd);
       
  2174 +      zlog_warn ("bytesread %d", bytesread);
       
  2175 +      /* get rid of the packet */
       
  2176 +      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
       
  2177 +      return ISIS_WARNING;
       
  2178 +    }
       
  2179 +  /*
       
  2180 +   * Filtering by llc field, discard packets sent by this host (other circuit)
       
  2181 +   */
       
  2182 +  if (!llc_check (llc) || s_addr.sll_pkttype == PACKET_OUTGOING)
       
  2183 +    {
       
  2184 +      /*  Read the packet into discard buff */
       
  2185 +      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
       
  2186 +      if (bytesread < 0)
       
  2187 +	zlog_warn ("isis_recv_pdu_bcast(): read() failed");
       
  2188 +      return ISIS_WARNING;
       
  2189 +    }
       
  2190 +
       
  2191 +  /* on lan we have to read to the static buff first */
       
  2192 +  bytesread = recvfrom (circuit->fd, sock_buff, circuit->interface->mtu, 0,
       
  2193 +			(struct sockaddr *) &s_addr, (socklen_t *) &addr_len);
       
  2194 +
       
  2195 +  /* then we lose the LLC */
       
  2196 +  stream_write (circuit->rcv_stream, sock_buff + LLC_LEN, bytesread - LLC_LEN);
       
  2197 +
       
  2198 +  memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen);
       
  2199 +
       
  2200 +  return ISIS_OK;
       
  2201 +}
       
  2202 +
       
  2203 +int
       
  2204 +isis_recv_pdu_p2p (struct isis_circuit *circuit, u_char * ssnpa)
       
  2205 +{
       
  2206 +  int bytesread, addr_len;
       
  2207 +  struct sockaddr_ll s_addr;
       
  2208 +
       
  2209 +  memset (&s_addr, 0, sizeof (struct sockaddr_ll));
       
  2210 +  addr_len = sizeof (s_addr);
       
  2211 +
       
  2212 +  /* we can read directly to the stream */
       
  2213 +  bytesread = stream_recvfrom (circuit->rcv_stream, circuit->fd,
       
  2214 +                               circuit->interface->mtu, 0,
       
  2215 +                               (struct sockaddr *) &s_addr, 
       
  2216 +                               (socklen_t *) &addr_len);
       
  2217 +
       
  2218 +  if (s_addr.sll_pkttype == PACKET_OUTGOING)
       
  2219 +    {
       
  2220 +      /*  Read the packet into discard buff */
       
  2221 +      bytesread = read (circuit->fd, discard_buff, sizeof (discard_buff));
       
  2222 +      if (bytesread < 0)
       
  2223 +	zlog_warn ("isis_recv_pdu_p2p(): read() failed");
       
  2224 +      return ISIS_WARNING;
       
  2225 +    }
       
  2226 +
       
  2227 +  /* If we don't have protocol type 0x00FE which is
       
  2228 +   * ISO over GRE we exit with pain :)
       
  2229 +   */
       
  2230 +  if (ntohs (s_addr.sll_protocol) != 0x00FE)
       
  2231 +    {
       
  2232 +      zlog_warn ("isis_recv_pdu_p2p(): protocol mismatch(): %X",
       
  2233 +		 ntohs (s_addr.sll_protocol));
       
  2234 +      return ISIS_WARNING;
       
  2235 +    }
       
  2236 +
       
  2237 +  memcpy (ssnpa, &s_addr.sll_addr, s_addr.sll_halen);
       
  2238 +
       
  2239 +  return ISIS_OK;
       
  2240 +}
       
  2241 +
       
  2242 +int
       
  2243 +isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
       
  2244 +{
       
  2245 +  /* we need to do the LLC in here because of P2P circuits, which will
       
  2246 +   * not need it
       
  2247 +   */
       
  2248 +  int written = 1;
       
  2249 +  struct sockaddr_ll sa;
       
  2250 +
       
  2251 +  stream_set_getp (circuit->snd_stream, 0);
       
  2252 +  memset (&sa, 0, sizeof (struct sockaddr_ll));
       
  2253 +  sa.sll_family = AF_PACKET;
       
  2254 +  sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
       
  2255 +  sa.sll_ifindex = circuit->interface->ifindex;
       
  2256 +  sa.sll_halen = ETH_ALEN;
       
  2257 +  if (level == 1)
       
  2258 +    memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
       
  2259 +  else
       
  2260 +    memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
       
  2261 +
       
  2262 +  /* on a broadcast circuit */
       
  2263 +  /* first we put the LLC in */
       
  2264 +  sock_buff[0] = 0xFE;
       
  2265 +  sock_buff[1] = 0xFE;
       
  2266 +  sock_buff[2] = 0x03;
       
  2267 +
       
  2268 +  /* then we copy the data */
       
  2269 +  memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
       
  2270 +	  stream_get_endp (circuit->snd_stream));
       
  2271 +
       
  2272 +  /* now we can send this */
       
  2273 +  written = sendto (circuit->fd, sock_buff,
       
  2274 +		    stream_get_endp(circuit->snd_stream) + LLC_LEN, 0,
       
  2275 +		    (struct sockaddr *) &sa, sizeof (struct sockaddr_ll));
       
  2276 +
       
  2277 +  return ISIS_OK;
       
  2278 +}
       
  2279 +
       
  2280 +int
       
  2281 +isis_send_pdu_p2p (struct isis_circuit *circuit, int level)
       
  2282 +{
       
  2283 +
       
  2284 +  int written = 1;
       
  2285 +  struct sockaddr_ll sa;
       
  2286 +
       
  2287 +  stream_set_getp (circuit->snd_stream, 0);
       
  2288 +  memset (&sa, 0, sizeof (struct sockaddr_ll));
       
  2289 +  sa.sll_family = AF_PACKET;
       
  2290 +  sa.sll_protocol = htons (stream_get_endp (circuit->snd_stream) + LLC_LEN);
       
  2291 +  sa.sll_ifindex = circuit->interface->ifindex;
       
  2292 +  sa.sll_halen = ETH_ALEN;
       
  2293 +  if (level == 1)
       
  2294 +    memcpy (&sa.sll_addr, ALL_L1_ISS, ETH_ALEN);
       
  2295 +  else
       
  2296 +    memcpy (&sa.sll_addr, ALL_L2_ISS, ETH_ALEN);
       
  2297 +
       
  2298 +
       
  2299 +  /* lets try correcting the protocol */
       
  2300 +  sa.sll_protocol = htons (0x00FE);
       
  2301 +  written = sendto (circuit->fd, circuit->snd_stream->data,
       
  2302 +		    stream_get_endp (circuit->snd_stream), 0, 
       
  2303 +		    (struct sockaddr *) &sa,
       
  2304 +		    sizeof (struct sockaddr_ll));
       
  2305 +
       
  2306 +  return ISIS_OK;
       
  2307 +}
       
  2308 diff --git a/isisd/isis_tlv.h b/isisd/isis_tlv.h
       
  2309 index 951a254..fc9f35f 100644
       
  2310 --- isisd/isis_tlv.h
       
  2311 +++ isisd/isis_tlv.h
       
  2312 @@ -152,6 +152,10 @@ struct lan_neigh
       
  2313    u_char LAN_addr[6];
       
  2314  };
       
  2315  
       
  2316 +#ifdef __SUNPRO_C
       
  2317 +#pragma pack(1)
       
  2318 +#endif
       
  2319 +
       
  2320  /* struct for LSP entry */
       
  2321  struct lsp_entry
       
  2322  {
       
  2323 @@ -161,6 +165,10 @@ struct lsp_entry
       
  2324    u_int16_t checksum;
       
  2325  } __attribute__ ((packed));
       
  2326  
       
  2327 +#ifdef __SUNPRO_C
       
  2328 +#pragma pack()
       
  2329 +#endif
       
  2330 +
       
  2331  /* struct for checksum */
       
  2332  struct checksum
       
  2333  {