Annotation of embedaddon/quagga/isisd/isis_dlpi.c, revision 1.1
1.1 ! misho 1: /*
! 2: * IS-IS Rout(e)ing protocol - isis_dlpi.c
! 3: *
! 4: * Copyright (C) 2001,2002 Sampo Saaristo
! 5: * Tampere University of Technology
! 6: * Institute of Communications Engineering
! 7: *
! 8: * This program is free software; you can redistribute it and/or modify it
! 9: * under the terms of the GNU General Public Licenseas published by the Free
! 10: * Software Foundation; either version 2 of the License, or (at your option)
! 11: * any later version.
! 12: *
! 13: * This program is distributed in the hope that it will be useful,but WITHOUT
! 14: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
! 15: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
! 16: * more details.
! 17:
! 18: * You should have received a copy of the GNU General Public License along
! 19: * with this program; if not, write to the Free Software Foundation, Inc.,
! 20: * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
! 21: */
! 22:
! 23: #include <zebra.h>
! 24: #if ISIS_METHOD == ISIS_METHOD_DLPI
! 25: #include <net/if.h>
! 26: #include <netinet/if_ether.h>
! 27: #include <sys/types.h>
! 28: #include <unistd.h>
! 29: #include <fcntl.h>
! 30: #include <stropts.h>
! 31: #include <poll.h>
! 32: #include <sys/dlpi.h>
! 33: #include <sys/pfmod.h>
! 34:
! 35: #include "log.h"
! 36: #include "stream.h"
! 37: #include "if.h"
! 38:
! 39: #include "isisd/dict.h"
! 40: #include "isisd/include-netbsd/iso.h"
! 41: #include "isisd/isis_constants.h"
! 42: #include "isisd/isis_common.h"
! 43: #include "isisd/isis_circuit.h"
! 44: #include "isisd/isis_flags.h"
! 45: #include "isisd/isisd.h"
! 46: #include "isisd/isis_network.h"
! 47:
! 48: #include "privs.h"
! 49:
! 50: extern struct zebra_privs_t isisd_privs;
! 51:
! 52: static t_uscalar_t dlpi_ctl[1024]; /* DLPI control messages */
! 53:
! 54: /*
! 55: * Table 9 - Architectural constants for use with ISO 8802 subnetworks
! 56: * ISO 10589 - 8.4.8
! 57: */
! 58:
! 59: u_char ALL_L1_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x14 };
! 60: u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 };
! 61: u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 };
! 62: u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 };
! 63:
! 64: static u_char sock_buff[8192];
! 65:
! 66: static u_short pf_filter[] =
! 67: {
! 68: ENF_PUSHWORD + 0, /* Get the SSAP/DSAP values */
! 69: ENF_PUSHLIT | ENF_CAND, /* Check them */
! 70: ISO_SAP | (ISO_SAP << 8),
! 71: ENF_PUSHWORD + 1, /* Get the control value */
! 72: ENF_PUSHLIT | ENF_AND, /* Isolate it */
! 73: #ifdef _BIG_ENDIAN
! 74: 0xFF00,
! 75: #else
! 76: 0x00FF,
! 77: #endif
! 78: ENF_PUSHLIT | ENF_CAND, /* Test for expected value */
! 79: #ifdef _BIG_ENDIAN
! 80: 0x0300
! 81: #else
! 82: 0x0003
! 83: #endif
! 84: };
! 85:
! 86: /*
! 87: * We would like to use something like libdlpi here, but that's not present on
! 88: * all versions of Solaris or on any non-Solaris system, so it's nowhere near
! 89: * as portable as we'd like. Thus, we use the standards-conformant DLPI
! 90: * interfaces plus the (optional; not needed) Solaris packet filter module.
! 91: */
! 92:
! 93: static void
! 94: dlpisend (int fd, const void *cbuf, size_t cbuflen,
! 95: const void *dbuf, size_t dbuflen, int flags)
! 96: {
! 97: const struct strbuf *ctlptr = NULL;
! 98: const struct strbuf *dataptr = NULL;
! 99: struct strbuf ctlbuf, databuf;
! 100:
! 101: if (cbuf != NULL)
! 102: {
! 103: memset (&ctlbuf, 0, sizeof (ctlbuf));
! 104: ctlbuf.len = cbuflen;
! 105: ctlbuf.buf = (void *)cbuf;
! 106: ctlptr = &ctlbuf;
! 107: }
! 108:
! 109: if (dbuf != NULL)
! 110: {
! 111: memset (&databuf, 0, sizeof (databuf));
! 112: databuf.len = dbuflen;
! 113: databuf.buf = (void *)dbuf;
! 114: dataptr = &databuf;
! 115: }
! 116:
! 117: /* We assume this doesn't happen often and isn't operationally significant */
! 118: if (putmsg (fd, ctlptr, dataptr, flags) == -1)
! 119: zlog_debug ("%s: putmsg: %s", __func__, safe_strerror (errno));
! 120: }
! 121:
! 122: static ssize_t
! 123: dlpirctl (int fd)
! 124: {
! 125: struct pollfd fds[1];
! 126: struct strbuf ctlbuf, databuf;
! 127: int flags, retv;
! 128:
! 129: do
! 130: {
! 131: /* Poll is used here in case the device doesn't speak DLPI correctly */
! 132: memset (fds, 0, sizeof (fds));
! 133: fds[0].fd = fd;
! 134: fds[0].events = POLLIN | POLLPRI;
! 135: if (poll (fds, 1, 1000) <= 0)
! 136: return -1;
! 137:
! 138: memset (&ctlbuf, 0, sizeof (ctlbuf));
! 139: memset (&databuf, 0, sizeof (databuf));
! 140: ctlbuf.maxlen = sizeof (dlpi_ctl);
! 141: ctlbuf.buf = (void *)dlpi_ctl;
! 142: databuf.maxlen = sizeof (sock_buff);
! 143: databuf.buf = (void *)sock_buff;
! 144: flags = 0;
! 145: retv = getmsg (fd, &ctlbuf, &databuf, &flags);
! 146:
! 147: if (retv < 0)
! 148: return -1;
! 149: }
! 150: while (ctlbuf.len == 0);
! 151:
! 152: if (!(retv & MORECTL))
! 153: {
! 154: while (retv & MOREDATA)
! 155: {
! 156: flags = 0;
! 157: retv = getmsg (fd, NULL, &databuf, &flags);
! 158: }
! 159: return ctlbuf.len;
! 160: }
! 161:
! 162: while (retv & MORECTL)
! 163: {
! 164: flags = 0;
! 165: retv = getmsg (fd, &ctlbuf, &databuf, &flags);
! 166: }
! 167: return -1;
! 168: }
! 169:
! 170: static int
! 171: dlpiok (int fd, t_uscalar_t oprim)
! 172: {
! 173: int retv;
! 174: dl_ok_ack_t *doa = (dl_ok_ack_t *)dlpi_ctl;
! 175:
! 176: retv = dlpirctl (fd);
! 177: if (retv < DL_OK_ACK_SIZE || doa->dl_primitive != DL_OK_ACK ||
! 178: doa->dl_correct_primitive != oprim)
! 179: {
! 180: return -1;
! 181: }
! 182: else
! 183: {
! 184: return 0;
! 185: }
! 186: }
! 187:
! 188: static int
! 189: dlpiinfo (int fd)
! 190: {
! 191: dl_info_req_t dir;
! 192: ssize_t retv;
! 193:
! 194: memset (&dir, 0, sizeof (dir));
! 195: dir.dl_primitive = DL_INFO_REQ;
! 196: /* Info_req uses M_PCPROTO. */
! 197: dlpisend (fd, &dir, sizeof (dir), NULL, 0, RS_HIPRI);
! 198: retv = dlpirctl (fd);
! 199: if (retv < DL_INFO_ACK_SIZE || dlpi_ctl[0] != DL_INFO_ACK)
! 200: return -1;
! 201: else
! 202: return retv;
! 203: }
! 204:
! 205: static int
! 206: dlpiopen (const char *devpath, ssize_t *acklen)
! 207: {
! 208: int fd, flags;
! 209:
! 210: fd = open (devpath, O_RDWR | O_NONBLOCK | O_NOCTTY);
! 211: if (fd == -1)
! 212: return -1;
! 213:
! 214: /* All that we want is for the open itself to be non-blocking, not I/O. */
! 215: flags = fcntl (fd, F_GETFL, 0);
! 216: if (flags != -1)
! 217: fcntl (fd, F_SETFL, flags & ~O_NONBLOCK);
! 218:
! 219: /* After opening, ask for information */
! 220: if ((*acklen = dlpiinfo (fd)) == -1)
! 221: {
! 222: close (fd);
! 223: return -1;
! 224: }
! 225:
! 226: return fd;
! 227: }
! 228:
! 229: static int
! 230: dlpiattach (int fd, int unit)
! 231: {
! 232: dl_attach_req_t dar;
! 233:
! 234: memset (&dar, 0, sizeof (dar));
! 235: dar.dl_primitive = DL_ATTACH_REQ;
! 236: dar.dl_ppa = unit;
! 237: dlpisend (fd, &dar, sizeof (dar), NULL, 0, 0);
! 238: return dlpiok (fd, dar.dl_primitive);
! 239: }
! 240:
! 241: static int
! 242: dlpibind (int fd)
! 243: {
! 244: dl_bind_req_t dbr;
! 245: int retv;
! 246: dl_bind_ack_t *dba = (dl_bind_ack_t *)dlpi_ctl;
! 247:
! 248: memset (&dbr, 0, sizeof (dbr));
! 249: dbr.dl_primitive = DL_BIND_REQ;
! 250: dbr.dl_service_mode = DL_CLDLS;
! 251: dlpisend (fd, &dbr, sizeof (dbr), NULL, 0, 0);
! 252:
! 253: retv = dlpirctl (fd);
! 254: if (retv < DL_BIND_ACK_SIZE || dba->dl_primitive != DL_BIND_ACK)
! 255: return -1;
! 256: else
! 257: return 0;
! 258: }
! 259:
! 260: static int
! 261: dlpimcast (int fd, const u_char *mcaddr)
! 262: {
! 263: struct {
! 264: dl_enabmulti_req_t der;
! 265: u_char addr[ETHERADDRL];
! 266: } dler;
! 267:
! 268: memset (&dler, 0, sizeof (dler));
! 269: dler.der.dl_primitive = DL_ENABMULTI_REQ;
! 270: dler.der.dl_addr_length = sizeof (dler.addr);
! 271: dler.der.dl_addr_offset = dler.addr - (u_char *)&dler;
! 272: memcpy (dler.addr, mcaddr, sizeof (dler.addr));
! 273: dlpisend (fd, &dler, sizeof (dler), NULL, 0, 0);
! 274: return dlpiok (fd, dler.der.dl_primitive);
! 275: }
! 276:
! 277: static int
! 278: dlpiaddr (int fd, u_char *addr)
! 279: {
! 280: dl_phys_addr_req_t dpar;
! 281: dl_phys_addr_ack_t *dpaa = (dl_phys_addr_ack_t *)dlpi_ctl;
! 282: int retv;
! 283:
! 284: memset (&dpar, 0, sizeof (dpar));
! 285: dpar.dl_primitive = DL_PHYS_ADDR_REQ;
! 286: dpar.dl_addr_type = DL_CURR_PHYS_ADDR;
! 287: dlpisend (fd, &dpar, sizeof (dpar), NULL, 0, 0);
! 288:
! 289: retv = dlpirctl (fd);
! 290: if (retv < DL_PHYS_ADDR_ACK_SIZE || dpaa->dl_primitive != DL_PHYS_ADDR_ACK)
! 291: return -1;
! 292:
! 293: if (dpaa->dl_addr_offset < DL_PHYS_ADDR_ACK_SIZE ||
! 294: dpaa->dl_addr_length != ETHERADDRL ||
! 295: dpaa->dl_addr_offset + dpaa->dl_addr_length > retv)
! 296: return -1;
! 297:
! 298: bcopy((char *)dpaa + dpaa->dl_addr_offset, addr, ETHERADDRL);
! 299: return 0;
! 300: }
! 301:
! 302: static int
! 303: open_dlpi_dev (struct isis_circuit *circuit)
! 304: {
! 305: int fd, unit, retval;
! 306: char devpath[MAXPATHLEN];
! 307: dl_info_ack_t *dia = (dl_info_ack_t *)dlpi_ctl;
! 308: ssize_t acklen;
! 309:
! 310: /* Only broadcast-type are supported at the moment */
! 311: if (circuit->circ_type != CIRCUIT_T_BROADCAST)
! 312: {
! 313: zlog_warn ("%s: non-broadcast interface %s", __func__,
! 314: circuit->interface->name);
! 315: return ISIS_WARNING;
! 316: }
! 317:
! 318: /* Try the vanity node first, if permitted */
! 319: if (getenv("DLPI_DEVONLY") == NULL)
! 320: {
! 321: (void) snprintf (devpath, sizeof(devpath), "/dev/net/%s",
! 322: circuit->interface->name);
! 323: fd = dlpiopen (devpath, &acklen);
! 324: }
! 325:
! 326: /* Now try as an ordinary Style 1 node */
! 327: if (fd == -1)
! 328: {
! 329: (void) snprintf (devpath, sizeof (devpath), "/dev/%s",
! 330: circuit->interface->name);
! 331: unit = -1;
! 332: fd = dlpiopen (devpath, &acklen);
! 333: }
! 334:
! 335: /* If that fails, try again as Style 2 */
! 336: if (fd == -1)
! 337: {
! 338: char *cp;
! 339:
! 340: cp = devpath + strlen (devpath);
! 341: while (--cp >= devpath && isdigit(*cp))
! 342: ;
! 343: unit = strtol(cp, NULL, 0);
! 344: *cp = '\0';
! 345: fd = dlpiopen (devpath, &acklen);
! 346:
! 347: /* If that too fails, then the device really doesn't exist */
! 348: if (fd == -1)
! 349: {
! 350: zlog_warn ("%s: unknown interface %s", __func__,
! 351: circuit->interface->name);
! 352: return ISIS_WARNING;
! 353: }
! 354:
! 355: /* Double check the DLPI style */
! 356: if (dia->dl_provider_style != DL_STYLE2)
! 357: {
! 358: zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 2",
! 359: circuit->interface->name, devpath);
! 360: close (fd);
! 361: return ISIS_WARNING;
! 362: }
! 363:
! 364: /* If it succeeds, then we need to attach to the unit specified */
! 365: dlpiattach (fd, unit);
! 366:
! 367: /* Reget the information, as it may be different per node */
! 368: if ((acklen = dlpiinfo (fd)) == -1)
! 369: {
! 370: close (fd);
! 371: return ISIS_WARNING;
! 372: }
! 373: }
! 374: else
! 375: {
! 376: /* Double check the DLPI style */
! 377: if (dia->dl_provider_style != DL_STYLE1)
! 378: {
! 379: zlog_warn ("open_dlpi_dev(): interface %s: %s is not style 1",
! 380: circuit->interface->name, devpath);
! 381: close (fd);
! 382: return ISIS_WARNING;
! 383: }
! 384: }
! 385:
! 386: /* Check that the interface we've got is the kind we expect */
! 387: if ((dia->dl_sap_length != 2 && dia->dl_sap_length != -2) ||
! 388: dia->dl_service_mode != DL_CLDLS || dia->dl_addr_length != ETHERADDRL + 2 ||
! 389: dia->dl_brdcst_addr_length != ETHERADDRL)
! 390: {
! 391: zlog_warn ("%s: unsupported interface type for %s", __func__,
! 392: circuit->interface->name);
! 393: close (fd);
! 394: return ISIS_WARNING;
! 395: }
! 396: switch (dia->dl_mac_type)
! 397: {
! 398: case DL_CSMACD:
! 399: case DL_ETHER:
! 400: case DL_100VG:
! 401: case DL_100VGTPR:
! 402: case DL_ETH_CSMA:
! 403: case DL_100BT:
! 404: break;
! 405: default:
! 406: zlog_warn ("%s: unexpected mac type on %s: %d", __func__,
! 407: circuit->interface->name, dia->dl_mac_type);
! 408: close (fd);
! 409: return ISIS_WARNING;
! 410: }
! 411:
! 412: circuit->sap_length = dia->dl_sap_length;
! 413:
! 414: /*
! 415: * The local hardware address is something that should be provided by way of
! 416: * sockaddr_dl for the interface, but isn't on Solaris. We set it here based
! 417: * on DLPI's reported address to avoid roto-tilling the world.
! 418: * (Note that isis_circuit_if_add on Solaris doesn't set the snpa.)
! 419: *
! 420: * Unfortunately, GLD is broken and doesn't provide the address after attach,
! 421: * so we need to be careful and use DL_PHYS_ADDR_REQ instead.
! 422: */
! 423: if (dlpiaddr (fd, circuit->u.bc.snpa) == -1)
! 424: {
! 425: zlog_warn ("open_dlpi_dev(): interface %s: unable to get MAC address",
! 426: circuit->interface->name);
! 427: close (fd);
! 428: return ISIS_WARNING;
! 429: }
! 430:
! 431: /* Now bind to SAP 0. This gives us 802-type traffic. */
! 432: if (dlpibind (fd) == -1)
! 433: {
! 434: zlog_warn ("%s: cannot bind SAP 0 on %s", __func__,
! 435: circuit->interface->name);
! 436: close (fd);
! 437: return ISIS_WARNING;
! 438: }
! 439:
! 440: /*
! 441: * Join to multicast groups according to
! 442: * 8.4.2 - Broadcast subnetwork IIH PDUs
! 443: */
! 444: retval = 0;
! 445: if (circuit->circuit_is_type & IS_LEVEL_1)
! 446: {
! 447: retval |= dlpimcast (fd, ALL_L1_ISS);
! 448: retval |= dlpimcast (fd, ALL_ISS);
! 449: }
! 450: if (circuit->circuit_is_type & IS_LEVEL_2)
! 451: retval |= dlpimcast (fd, ALL_L2_ISS);
! 452:
! 453: if (retval != 0)
! 454: {
! 455: zlog_warn ("%s: unable to join multicast on %s", __func__,
! 456: circuit->interface->name);
! 457: close (fd);
! 458: return ISIS_WARNING;
! 459: }
! 460:
! 461: /* Push on the packet filter to avoid stray 802 packets */
! 462: if (ioctl (fd, I_PUSH, "pfmod") == 0)
! 463: {
! 464: struct packetfilt pfil;
! 465: struct strioctl sioc;
! 466:
! 467: pfil.Pf_Priority = 0;
! 468: pfil.Pf_FilterLen = sizeof (pf_filter) / sizeof (u_short);
! 469: memcpy (pfil.Pf_Filter, pf_filter, sizeof (pf_filter));
! 470: /* pfmod does not support transparent ioctls */
! 471: sioc.ic_cmd = PFIOCSETF;
! 472: sioc.ic_timout = 5;
! 473: sioc.ic_len = sizeof (struct packetfilt);
! 474: sioc.ic_dp = (char *)&pfil;
! 475: if (ioctl (fd, I_STR, &sioc) == -1)
! 476: zlog_warn("%s: could not perform PF_IOCSETF on %s",
! 477: __func__, circuit->interface->name);
! 478: }
! 479:
! 480: circuit->fd = fd;
! 481:
! 482: return ISIS_OK;
! 483: }
! 484:
! 485: /*
! 486: * Create the socket and set the tx/rx funcs
! 487: */
! 488: int
! 489: isis_sock_init (struct isis_circuit *circuit)
! 490: {
! 491: int retval = ISIS_OK;
! 492:
! 493: if (isisd_privs.change (ZPRIVS_RAISE))
! 494: zlog_err ("%s: could not raise privs, %s", __func__, safe_strerror (errno));
! 495:
! 496: retval = open_dlpi_dev (circuit);
! 497:
! 498: if (retval != ISIS_OK)
! 499: {
! 500: zlog_warn ("%s: could not initialize the socket", __func__);
! 501: goto end;
! 502: }
! 503:
! 504: if (circuit->circ_type == CIRCUIT_T_BROADCAST)
! 505: {
! 506: circuit->tx = isis_send_pdu_bcast;
! 507: circuit->rx = isis_recv_pdu_bcast;
! 508: }
! 509: else
! 510: {
! 511: zlog_warn ("isis_sock_init(): unknown circuit type");
! 512: retval = ISIS_WARNING;
! 513: goto end;
! 514: }
! 515:
! 516: end:
! 517: if (isisd_privs.change (ZPRIVS_LOWER))
! 518: zlog_err ("%s: could not lower privs, %s", __func__, safe_strerror (errno));
! 519:
! 520: return retval;
! 521: }
! 522:
! 523: int
! 524: isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa)
! 525: {
! 526: struct pollfd fds[1];
! 527: struct strbuf ctlbuf, databuf;
! 528: int flags, retv;
! 529: dl_unitdata_ind_t *dui = (dl_unitdata_ind_t *)dlpi_ctl;
! 530:
! 531: memset (fds, 0, sizeof (fds));
! 532: fds[0].fd = circuit->fd;
! 533: fds[0].events = POLLIN | POLLPRI;
! 534: if (poll (fds, 1, 0) <= 0)
! 535: return ISIS_WARNING;
! 536:
! 537: memset (&ctlbuf, 0, sizeof (ctlbuf));
! 538: memset (&databuf, 0, sizeof (databuf));
! 539: ctlbuf.maxlen = sizeof (dlpi_ctl);
! 540: ctlbuf.buf = (void *)dlpi_ctl;
! 541: databuf.maxlen = sizeof (sock_buff);
! 542: databuf.buf = (void *)sock_buff;
! 543: flags = 0;
! 544: retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags);
! 545:
! 546: if (retv < 0)
! 547: {
! 548: zlog_warn ("isis_recv_pdu_bcast: getmsg failed: %s",
! 549: safe_strerror (errno));
! 550: return ISIS_WARNING;
! 551: }
! 552:
! 553: if (retv & (MORECTL | MOREDATA))
! 554: {
! 555: while (retv & (MORECTL | MOREDATA))
! 556: {
! 557: flags = 0;
! 558: retv = getmsg (circuit->fd, &ctlbuf, &databuf, &flags);
! 559: }
! 560: return ISIS_WARNING;
! 561: }
! 562:
! 563: if (ctlbuf.len < DL_UNITDATA_IND_SIZE ||
! 564: dui->dl_primitive != DL_UNITDATA_IND)
! 565: return ISIS_WARNING;
! 566:
! 567: if (dui->dl_src_addr_length != ETHERADDRL + 2 ||
! 568: dui->dl_src_addr_offset < DL_UNITDATA_IND_SIZE ||
! 569: dui->dl_src_addr_offset + dui->dl_src_addr_length > ctlbuf.len)
! 570: return ISIS_WARNING;
! 571:
! 572: memcpy (ssnpa, (char *)dui + dui->dl_src_addr_offset +
! 573: (circuit->sap_length > 0 ? circuit->sap_length : 0), ETHERADDRL);
! 574:
! 575: if (databuf.len < LLC_LEN || sock_buff[0] != ISO_SAP ||
! 576: sock_buff[1] != ISO_SAP || sock_buff[2] != 3)
! 577: return ISIS_WARNING;
! 578:
! 579: stream_write (circuit->rcv_stream, sock_buff + LLC_LEN,
! 580: databuf.len - LLC_LEN);
! 581: stream_set_getp (circuit->rcv_stream, 0);
! 582:
! 583: return ISIS_OK;
! 584: }
! 585:
! 586: int
! 587: isis_send_pdu_bcast (struct isis_circuit *circuit, int level)
! 588: {
! 589: dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl;
! 590: char *dstaddr;
! 591: u_short *dstsap;
! 592:
! 593: stream_set_getp (circuit->snd_stream, 0);
! 594:
! 595: memset (dur, 0, sizeof (*dur));
! 596: dur->dl_primitive = DL_UNITDATA_REQ;
! 597: dur->dl_dest_addr_length = ETHERADDRL + 2;
! 598: dur->dl_dest_addr_offset = sizeof (*dur);
! 599:
! 600: dstaddr = (char *)(dur + 1);
! 601: if (circuit->sap_length < 0)
! 602: {
! 603: dstsap = (u_short *)(dstaddr + ETHERADDRL);
! 604: }
! 605: else
! 606: {
! 607: dstsap = (u_short *)dstaddr;
! 608: dstaddr += circuit->sap_length;
! 609: }
! 610: if (level == 1)
! 611: memcpy (dstaddr, ALL_L1_ISS, ETHERADDRL);
! 612: else
! 613: memcpy (dstaddr, ALL_L2_ISS, ETHERADDRL);
! 614: /* Note: DLPI SAP values are in host byte order */
! 615: *dstsap = stream_get_endp (circuit->snd_stream) + LLC_LEN;
! 616:
! 617: sock_buff[0] = ISO_SAP;
! 618: sock_buff[1] = ISO_SAP;
! 619: sock_buff[2] = 0x03;
! 620: memcpy (sock_buff + LLC_LEN, circuit->snd_stream->data,
! 621: stream_get_endp (circuit->snd_stream));
! 622: dlpisend (circuit->fd, dur, sizeof (*dur) + dur->dl_dest_addr_length,
! 623: sock_buff, stream_get_endp (circuit->snd_stream) + LLC_LEN, 0);
! 624: return ISIS_OK;
! 625: }
! 626:
! 627: #endif /* ISIS_METHOD == ISIS_METHOD_DLPI */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>