/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* llc1 - an LLC Class 1 MUX compatible with SunConnect LLC2 uses DLPI
* interface. Its primary use is to support RPL for network boot but can be
* used by other protocols.
*/
#include <sys/sysmacros.h>
#include <sys/ethernet.h>
/*
* function prototypes, etc.
*/
static int llc1_uwsrv(queue_t *q);
static int llc1_lrsrv(queue_t *q);
static void llc1remque(void *arg);
static void llc1error();
static int llc1_subs_unbind(void);
static int llc1_req_info(queue_t *q);
/*
* the standard streams glue for defining the type of streams entity and the
* operational parameters.
*/
"llc1",
0,
LLC1_HIWATER, /* high water mark */
LLC1_LOWATER, /* low water mark */
};
NULL,
NULL,
NULL,
};
NULL,
NULL,
NULL,
};
putq,
NULL,
NULL,
NULL,
};
NULL,
NULL,
NULL,
NULL,
NULL,
};
};
/*
*/
#if !defined(BUILD_STATIC)
/* define the "ops" structure for a STREAMS driver */
/*
* Module linkage information for the kernel.
*/
&mod_driverops, /* Type of module. This one is a driver */
"LLC Class 1 Driver",
&llc1_ops, /* driver ops */
};
};
int
_init(void)
{
return (mod_install(&modlinkage));
}
int
_fini(void)
{
return (mod_remove(&modlinkage));
}
int
{
}
#endif
#ifdef LLC1_DEBUG
#endif
/*
* Allocate and zero-out "number" structures each of type "structure" in
* kernel memory.
*/
/*
* llc1_attach - init time attach support When the hardware specific attach
* is called, it must call this procedure with the device class structure
*/
static int
{
if (cmd != DDI_ATTACH)
return (DDI_FAILURE);
/*
* there isn't any hardware but we do need to initialize things
*/
/* make sure minor device lists are initialized */
/* make sure device list is initialized */
}
/*
* now do all the DDI stuff necessary
*/
/*
* create the file system device node
*/
return (DDI_FAILURE);
}
devinfo, 0, "multisize", 0);
if (llc1_device_list.llc1_multisize == 0)
return (DDI_SUCCESS);
}
/*
* llc1_detach standard kernel interface routine
*/
static int
{
if (cmd != DDI_DETACH) {
return (DDI_FAILURE);
}
if (llc1_device_list.llc1_ndevice > 0)
return (DDI_FAILURE);
/* remove all mutex and locks */
return (DDI_SUCCESS);
}
/*
* llc1_devinfo(dev, cmd, arg, result) standard kernel devinfo lookup
* function
*/
/*ARGSUSED2*/
static int
{
int error;
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
error = DDI_FAILURE;
} else {
error = DDI_SUCCESS;
}
break;
case DDI_INFO_DEVT2INSTANCE:
*result = (void *)0;
error = DDI_SUCCESS;
break;
default:
error = DDI_FAILURE;
}
return (error);
}
/*
* llc1_open()
* LLC1 open routine, called when device is opened by the user
*/
/*ARGSUSED2*/
static int
{
int status = 0;
ASSERT(q);
/*
* Stream already open, sucess.
*/
if (q->q_ptr)
return (0);
/*
* llc1 devices, but open and close are not frequent so should not
* induce much, if any delay.
*/
/* need to find a minor dev */
if (minordev == 0) {
return (ENXIO);
}
} else {
return (ENXIO);
}
}
/*
* get a per-stream structure and link things together so we
* can easily find them later.
*/
/*
* fill in the structure and state info
*/
qprocson(q); /* start the queues running */
return (status);
}
/*
* llc1_close(q)
* normal stream close call checks current status and cleans up
* data structures that were dynamically allocated
*/
/*ARGSUSED1*/
static int
{
ASSERT(q);
qprocsoff(q);
/* completely disassociate the stream from the device */
}
int i;
for (i = 0; i < llc1_device_list.llc1_multisize; i++) {
/*
* disable from stream and possibly
* lower stream
*/
if (llc1->llc_mac_info &&
mcast);
}
}
}
return (0);
}
/*
* llc1_uwput()
* general llc stream write put routine. Receives ioctl's from
* user level and data from upper modules and processes them immediately.
* procedure.
*/
static int
{
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
#endif
case M_IOCTL: /* no waiting in ioctl's */
(void) llc1_ioctl(q, mp);
break;
case M_FLUSH: /* canonical flush handling */
flushq(q, 0);
} else
break;
/* for now, we will always queue */
case M_PROTO:
case M_PCPROTO:
break;
case M_DATA:
/* fast data / raw support */
break;
}
/* need to do further checking */
break;
default:
#ifdef LLC1_DEBUG
if (llc1_debug & LLCERRS)
printf("llc1: Unexpected packet type from queue: %d\n",
#endif
}
return (0);
}
/*
* llc1_lrsrv()
* called when data is put into the service queue from below.
* Determines additional processing that might be needed and sends the data
* upstream in the form of a Data Indication packet.
*/
static int
{
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
printf("llc1_rsrv(%x)\n", q);
if (llc1_debug & LLCRECV) {
printf("NULL macinfo");
panic("null macinfo in lrsrv");
/*NOTREACHED*/
}
printf("\n");
}
#endif
/*
* determine where message goes, then call the proper handler
*/
case M_PROTO:
case M_PCPROTO:
/* only some primitives ever get passed through */
switch (prim->dl_primitive) {
case DL_INFO_ACK:
/*
* we are in the midst of completing
* info
*/
/*
* size of max header
* (including SNAP)
*/
}
/*
* need to put the lower stream into
* DLRAW mode. Currently only DL_ETHER
* or DL_CSMACD
*/
case DL_ETHER:
case DL_CSMACD:
/*
* raw mode is optimal so ask
* for it * we might not get
* it but that's OK
*/
break;
default:
/*
* don't want raw mode so don't
* ask for it
*/
break;
}
} else {
/* address was wrong before */
}
break;
case DL_BIND_ACK:
/*
* if we had to bind, the macaddr is wrong
* so get it again
*/
(void) llc1_req_info(q);
break;
case DL_UNITDATA_IND:
/* when not using raw mode we get these */
break;
case DL_ERROR_ACK:
/* binding is a special case */
DL_BIND_REQ) {
} else
break;
case DL_PHYS_ADDR_ACK:
break;
case DL_OK_ACK:
/* FALLTHROUGH */
default:
}
break;
case M_IOCACK:
/* probably our DLIOCRAW completing */
/* we can use this form */
break;
}
/* need to find the correct queue */
break;
case M_IOCNAK:
break;
}
/* need to find the correct queue */
break;
case M_DATA:
break;
}
}
return (0);
}
/*
* llc1_uwsrv - Incoming messages are processed according to the DLPI
* protocol specification
*/
static int
{
int err;
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
printf("llc1_wsrv(%x)\n", q);
#endif
case M_PROTO: /* Will be an DLPI message of some type */
case M_PCPROTO:
/* quit while we're ahead */
#ifdef LLC1_DEBUG
if (llc1_debug & LLCERRS)
"llc1_cmds: nonfatal err=%d\n",
err);
#endif
return (0);
} else {
dlerrorack(q, mp,
err, 0);
}
}
break;
case M_DATA:
/*
* retry of a previously processed
* UNITDATA_REQ or is a RAW message from
* above
*/
break;
/* This should never happen */
default:
#ifdef LLC1_DEBUG
if (llc1_debug & LLCERRS)
printf("llc1_wsrv: type(%x) not supported\n",
#endif
break;
}
}
return (0);
}
/*
* llc1_multicast used to determine if the address is a multicast address for
* this user.
*/
int
{
int i;
for (i = 0; i < lld->llc_multicnt; i++)
return (1);
return (0);
}
/*
* llc1_ioctl handles all ioctl requests passed downstream. This routine is
* passed a pointer to the message block with the ioctl request in it, and a
* pointer to the queue so it can respond to the ioctl request with an ack.
*/
int llc1_doreqinfo;
static void
{
int error;
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
#endif
/* XXX need to lock the data structures */
case I_PLINK:
case I_LINK:
return;
}
/* tentative */
macinfo->llcp_lqtop = q;
/* need to do an info_req before an info_req or attach */
/* initiate getting the info */
return;
case I_PUNLINK:
case I_UNLINK:
macinfo !=
/* found it */
/* remove from device list */
/* remove any mcast structs */
sizeof (llc_mcast_t) *
}
/* remove any kstat counters */
/* finish any necessary setup */
if (llc1_device_list.llc1_ndevice == 0)
return;
}
}
/*
* what should really be done here -- force errors on all
* streams?
*/
return;
case L_SETPPA:
if (error != 0) {
return;
}
return;
}
return;
case L_GETPPA:
return;
}
} else {
if (error != 0) {
return;
}
}
else
return;
default:
}
}
/*
* llc1_setppa(snioc) this function sets the real PPA number for a previously
* I_LINKED stream. Be careful to select the macinfo struct associated
* with our llc struct, to avoid erroneous references.
*/
static int
{
return (0);
}
return (-1);
}
/*
* llc1_getppa(macinfo, snioc) returns the PPA for this stream
*/
static int
{
return (-1);
return (0);
}
/*
* llc1_cmds - process the DL commands as defined in dlpi.h
*/
static int
{
int result = 0;
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
printf("llc1_cmds(%x, %x):dlp=%x, dlp->dl_primitive=%d\n",
#endif
switch (dlp->dl_primitive) {
case DL_BIND_REQ:
break;
case DL_UNBIND_REQ:
break;
case DL_SUBS_BIND_REQ:
break;
case DL_SUBS_UNBIND_REQ:
result = llc1_subs_unbind();
break;
case DL_UNITDATA_REQ:
break;
case DL_INFO_REQ:
break;
case DL_ATTACH_REQ:
break;
case DL_DETACH_REQ:
break;
case DL_ENABMULTI_REQ:
break;
case DL_DISABMULTI_REQ:
break;
case DL_XID_REQ:
break;
case DL_XID_RES:
break;
case DL_TEST_REQ:
break;
case DL_TEST_RES:
break;
case DL_SET_PHYS_ADDR_REQ:
break;
case DL_PHYS_ADDR_REQ:
} else {
}
break;
case DL_PROMISCON_REQ:
case DL_PROMISCOFF_REQ:
break;
default:
#ifdef LLC1_DEBUG
if (llc1_debug & LLCERRS)
printf("llc1_cmds: Received unknown primitive: %d\n",
dlp->dl_primitive);
#endif
result = DL_BADPRIM;
break;
}
return (result);
}
/*
* llc1_bind - determine if a SAP is already allocated and whether it is
* legal to do the bind at this time
*/
static int
{
int sap;
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
#endif
#ifdef LLC1_DEBUG
if (llc1_debug & LLCPROT)
#endif
return (DL_OUTSTATE);
#ifdef LLC1_DEBUG
if (llc1_debug & LLCERRS)
#endif
return (DL_OUTSTATE);
}
return (DL_UNSUPPORTED);
}
/*
* prohibit group saps. An exception is the broadcast sap which is,
* unfortunately, used by SUNSelect to indicate Novell Netware in
* 802.3 mode. Really should use a very non-802.2 SAP like 0xFFFF
* or -2.
*/
sap > 0xFFFF) {
return (DL_BADSAP);
}
/* if we fall through, then the SAP is legal */
if (sap == 0xFF) {
else
return (DL_BADSAP);
}
if (sap > 0xFF) {
/* this is SNAP, so set things up */
/* mark as SNAP but allow OID to be added later */
}
#ifdef LLC1_DEBUG
if (llc1_debug & LLCPROT)
#endif
/* ACK the BIND, if possible */
return (LLCE_OK);
}
/*
* llc1_unbind - perform an unbind of an LSAP or ether type on the stream.
* The stream is still open and can be re-bound.
*/
static int
{
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
#endif
return (DL_OUTSTATE);
#ifdef LLC1_DEBUG
if (llc1_debug & LLCERRS)
printf("llc1_unbind: wrong state (%d)\n",
#endif
return (DL_OUTSTATE);
}
return (LLCE_OK);
}
/*
* llc1_inforeq - generate the response to an info request
*/
static int
{
int bufsize;
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
#endif
else
bufsize = sizeof (dl_info_ack_t) +
if (nmp) {
if (lld->llc_mac_info)
dlp->dl_min_sdu = 0;
/* now append physical address */
if (lld->llc_mac_info) {
}
/* and the broadcast address */
} else {
}
}
return (LLCE_OK);
}
/*
* llc1_unitdata
* message (first mblock), data is in remainder of message.
*
* NOTE: We are reusing the DL_unitdata_req mblock; if llc header gets any
* bigger, recheck to make sure it still fits! We assume that we have a
* 64-byte dblock for this, since a DL_unitdata_req is 20 bytes and the next
* larger dblock size is 64.
*/
static int
{
long msglen;
int xmt_type = 0;
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
#endif
return (DL_OUTSTATE);
#ifdef LLC1_DEBUG
if (llc1_debug & LLCERRS)
printf("llc1_unitdata: wrong state (%d)\n",
#endif
return (DL_OUTSTATE);
}
/* need the destination address in all cases */
/*
* make a valid header for transmission
*/
/* need a buffer big enough for the headers */
/* fill in type dependent fields */
/* set length with llc header size */
sizeof (struct llchdr));
/* need an LLC header, otherwise is Novell */
/* bound sap is always source */
/* destination sap */
/* always Unnumbered Information */
}
} else {
/* set length without llc header size */
/* we don't do anything else for Netware */
}
xmt_type = 2;
else
xmt_type = 1;
}
break;
default: /* either RAW or unknown, send as is */
break;
}
} else {
/* need to format a DL_UNITDATA_REQ with LLC1 header inserted */
BPRI_MED);
return (DL_UNDELIVERABLE);
/*
* if we are using SNAP, insert the header here
*/
}
xmt_type = 2;
else
xmt_type = 1;
}
}
switch (xmt_type) {
case 1:
break;
case 2:
break;
}
return (LLCE_OK); /* this is almost correct, the result */
} else {
}
return (LLCE_OK);
}
/*
* llc1_recv(macinfo, mp)
* called with an ethernet packet in a mblock; must decide
* whether packet is for us and which streams to queue it to. This routine is
* called with locally originated packets for loopback.
*/
static void
{
#ifdef LLC1_DEBUG
if (llc1_debug & LLCTRACE)
#endif
/* check to see if really LLC1 XXX */
/* also need to make sure to keep address info */
if (i < 60) {
}
}
} else {
/* Note that raw mode currently assumes Ethernet */
sizeof (struct ether_header));
if (i < 60) {
}
}
#ifdef LLC1_DEBUG
if (llc1_debug & LLCRECV) {
}
#endif
statcnt_brdcst = 1;
} else {
}
/*
* Note that the NULL SAP is a special case. It is associated with
* the MAC layer and not the LLC layer so should be handled
* independently of any STREAM.
*/
if (msgsap == LLC_NULL_SAP) {
/* only XID and TEST ever processed, UI is dropped */
} else
/*
* is this a potentially usable SAP on the
* right MAC layer?
*/
continue;
}
#ifdef LLC1_DEBUG
if (llc1_debug & LLCRECV)
"llc1_recv: type=%d, sap=%x, pkt-dsap=%x\n",
msgsap);
#endif
lld->llc_multicnt > 0 &&
valid |= 4;
/* promiscuous mode */
valid = 1;
/* promiscuous streams */
(valid &&
msgsap == LLC_GLOBAL_SAP))) {
/* sap matches */
if (msgsap == LLC_SNAP_SAP &&
LLC_SNAP) {
if (!llc1_snap_match(lld,
continue;
}
#ifdef LLC1_DEBUG
if (llc1_debug & LLCRECV)
"llc1_recv: canput failed\n");
#endif
continue;
}
/* check for Novell special handling */
if (msgsap == LLC_GLOBAL_SAP &&
/* A Novell packet */
continue;
}
case LLC_UI:
/*
* this is an Unnumbered Information
* packet so form a DL_UNITDATA_IND and
* send to user
*/
break;
case LLC_XID:
/*
* this is either an XID request or
* response. We either handle directly
* (if user hasn't requested to handle
* itself) or send to user. We also
* must check if a response if user
* handled so that we can send correct
* message form
*/
} else {
/*
* hand to the user for
* handling. if this is a
* "request", generate a
* DL_XID_IND. If it is a
* "response" to one of our
* requests, generate a
* DL_XID_CON.
*/
}
break;
case LLC_TEST:
/*
* this is either a TEST request or
* response. We either handle
* directly (if user hasn't
* requested to handle itself)
* or send to user. We also
* must check if a response if
* user handled so that we can
* send correct message form
*/
} else {
/*
* hand to the user for
* handling. if this is
* a "request",
* generate a
* DL_TEST_IND. If it
* is a "response" to
* one of our requests,
* generate a
* DL_TEST_CON.
*/
}
break;
default:
break;
}
}
}
if (nmcast > 0)
if (statcnt_brdcst) {
}
if (statcnt_normal) {
}
}
/*
* llc1_local - check to see if the message is addressed to this system by
* comparing with the board's address.
*/
static int
{
macinfo->llcp_addrlen) == 0);
}
/*
* llc1_broadcast - check to see if a broadcast address is the destination of
* this received packet
*/
static int
{
macinfo->llcp_addrlen) == 0);
}
/*
* llc1attach(q, mp) DLPI DL_ATTACH_REQ this attaches the stream to a PPA
*/
static int
{
return (DL_OUTSTATE);
}
/*
* someone else has a lock held. To avoid deadlock,
* release the READER lock and block on a WRITER
* lock. This will let things continue safely.
*/
}
/*
* We may have found the correct PPA
* check to see if linking has finished.
* Use explicit flag checks for incorrect
* state, and use negative values for "tenative"
* llcp_ppas, to avoid erroneous attaches.
*/
if (mac->llcp_flags &
(LLC1_LINKED|LLC1_DEF_PPA)) {
return (DL_INITFAILED);
return (DL_BADPPA);
}
/* this links us to the PPA */
mac->llcp_nstreams++;
return (LLCE_OK);
}
}
return (DL_BADPPA);
}
/*
* llc1unattach(q, mp) DLPI DL_DETACH_REQ detaches the mac layer from the
* stream
*/
static int
{
int state;
int i;
if (state != DL_UNBOUND)
return (DL_OUTSTATE);
/* can now detach from the PPA */
/*
* someone else has a lock held. To avoid deadlock,
* release the READER lock and block on a WRITER
* lock. This will let things continue safely.
*/
}
for (i = 0; i < llc1_device_list.llc1_multisize; i++) {
/* disable from stream and possibly lower */
mcast);
}
}
}
if (llc->llc_mac_info)
if (mp) {
}
return (LLCE_OK);
}
/*
* llc1_enable_multi enables multicast address on the stream if the mac layer
* isn't enabled for this address, enable at that level as well.
*/
static int
{
int i;
#if defined(LLC1_DEBUG)
if (llc1_debug & LLCPROT) {
}
#endif
return (DL_OUTSTATE);
/*
* check to see if this multicast address is valid if it is, then
* check to see if it is already in the per stream table and the per
* device table if it is already in the per stream table, if it isn't
* in the per device, add it. If it is, just set a pointer. If it
* isn't, allocate what's necessary.
*/
/* request appears to be valid */
/* does this address appear in current table? */
/* no mcast addresses -- allocate table */
return (DL_SYSERR);
} else {
for (i = 0; i < llc1_device_list.llc1_multisize; i++) {
/* this is a match -- just succeed */
return (LLCE_OK);
}
}
}
/*
* there wasn't one so check to see if the mac layer has one
*/
return (DL_SYSERR);
}
i < llc1_device_list.llc1_multisize; i++) {
break;
}
}
if (nmp) {
}
/* find an empty slot to fill in */
if (mcast->llcm_refcnt == 0) {
break;
}
}
}
for (i = 0; i < llc1_device_list.llc1_multisize; i++) {
mcast->llcm_refcnt++;
return (LLCE_OK);
}
}
}
status = DL_TOOMANY;
}
return (status);
}
/*
* llc1_disable_multi disable the multicast address on the stream if last
* reference for the mac layer, disable there as well
*/
static int
{
#if defined(LLC1_DEBUG)
if (llc1_debug & LLCPROT) {
}
#endif
return (DL_OUTSTATE);
/* request appears to be valid */
/* does this address appear in current table? */
for (i = 0; i < llc->llc_multicnt; i++)
mcast->llcm_refcnt &&
mcast);
return (LLCE_OK);
}
status = DL_NOTENAB;
}
}
return (status);
}
/*
* llc1_send_disable_multi(llc, macinfo, mcast) this function is used to
* disable a multicast address if the reference count goes to zero. The
* disable request will then be forwarded to the lower stream.
*/
static void
{
return;
}
return;
}
if (--mcast->llcm_refcnt > 0)
return;
if (mp) {
}
}
/*
* llc1_findminor(device) searches the per device class list of STREAMS for
* the first minor number not used. Note that we currently don't allocate
* minor 0.
*/
static minor_t
{
goto nextminor;
}
return (minor);
/* don't need to do anything */
;
}
/*NOTREACHED*/
return (0);
}
/*
* llc1_req_info(q) simply construct a DL_INFO_REQ to be sent to the lower
* stream this is used to populate the macinfo structure.
*/
static int
{
return (-1);
return (0);
}
/*
* llc1_req_raw(macinfo) request that the lower stream enter DLIOCRAW mode
*/
static void
{
return;
}
/*
* llc1_send_bindreq
* if lower stream isn't bound, bind it to something appropriate
*/
static void
{
/* have to quite sometime if the world is failing */
return;
}
return;
bind->dl_max_conind = 0;
bind->dl_conn_mgmt = 0;
bind->dl_xidtest_flg = 0;
}
/*
* llc1_form_udata(lld, macinfo, mp) format a DL_UNITDATA_IND message to be
* sent to the user
*/
static mblk_t *
{
/* allocate the DL_UNITDATA_IND M_PROTO header */
/* might as well discard since we can't go further */
return (NULL);
}
sizeof (struct llchdr);
else
}
/*
* now setup the DL_UNITDATA_IND header
*/
} else {
}
} else {
}
0x1;
} else {
return (mp); /* we can't do anything */
}
/* if we end up here, we only want to patch the existing M_PROTO */
}
#ifdef LLC1_DEBUG
if (llc1_debug & LLCRECV)
printf("llc1_recv: queued message to %x (%d)\n",
#endif
/* enqueue for the service routine to process */
return (mp);
}
/*
* llc1_xid_reply(macinfo, mp) automatic reply to an XID command
*/
static mblk_t *
{
} else {
return (mp);
}
/* we only want to respond to commands to avoid response loops */
return (mp);
return (mp);
}
/*
* now construct the XID reply frame
*/
sizeof (struct llchdr));
} else {
return (mp);
}
/* mark it a response */
return (mp);
}
/*
* llc1_xid_ind_con(lld, macinfo, mp) form a DL_XID_IND or DL_XID_CON message
* to send to the user since it was requested that the user process these
* messages
*/
static mblk_t *
{
int raw;
BPRI_MED);
return (mp);
} else {
return (mp);
}
if (raw) {
} else {
}
if (raw) {
} else {
}
} else {
}
if (raw) {
(sizeof (struct ether_header) + sizeof (struct llchdr))) {
sizeof (struct ether_header) +
sizeof (struct llchdr);
}
}
sizeof (struct llchdr)) {
}
return (mp);
}
/*
* llc1_xid_req_res(q, mp, req_or_res) the user wants to send an XID message
* or response construct a proper message and put on the net
*/
static int
{
return (DL_OUTSTATE);
return (DL_NOTSUPPORTED);
return (DL_XIDAUTO);
return (DL_BADPRIM);
}
sizeof (struct llchdr_xid), BPRI_MED);
return (LLCE_NOBUFFER);
sizeof (struct ether_header) + sizeof (struct llchdr);
} else {
return (LLCE_NOBUFFER);
}
}
return (LLCE_OK);
}
/*
* llc1_test_reply(macinfo, mp)
* automatic reply to a TEST message
*/
static mblk_t *
{
int poll_final;
return (mp);
} else {
}
/* we only want to respond to commands to avoid response loops */
return (mp);
}
/*
* now construct the TEST reply frame
*/
/* make into a request */
} else {
}
/* mark it as a response */
return (mp);
}
/*
* llc1_test_ind_con(lld, macinfo, mp) form a DL_TEST_IND or DL_TEST_CON
* message to send to the user since it was requested that the user process
* these messages
*/
static mblk_t *
{
int raw;
return (NULL);
} else {
return (mp);
}
if (raw) {
} else {
}
if (raw) {
} else {
}
} else {
}
if (raw) {
(sizeof (struct ether_header) + sizeof (struct llchdr))) {
sizeof (struct ether_header) +
sizeof (struct llchdr);
}
}
sizeof (struct llchdr)) {
}
return (mp);
}
/*
* llc1_test_req_res(q, mp, req_or_res) the user wants to send a TEST
* message or response construct a proper message and put on the net
*/
static int
{
return (DL_OUTSTATE);
return (DL_NOTSUPPORTED);
return (DL_TESTAUTO);
test->dl_dest_addr_length)) {
return (DL_BADPRIM);
}
BPRI_MED);
return (LLCE_NOBUFFER);
sizeof (struct ether_header) + sizeof (struct llchdr);
} else {
return (LLCE_NOBUFFER);
}
}
return (LLCE_OK);
}
/*
* llc1_find_waiting(macinfo, mp, prim) look for a stream waiting for a
* response to a message identified by prim and send it to the user.
*/
static void
{
return;
}
}
static void
{
}
static void
{
}
/* VARARGS */
static void
{
static long last;
static char *lastfmt;
/*
* Don't print same error message too often.
*/
now = gethrestime_sec();
return;
}
/*ARGSUSED1*/
static int
{
return (0);
return (0);
}
static void
{
/*
* Note that the temporary macinfo->llcp_ppa number is negative.
*/
sizeof (struct llc_stats) / sizeof (long), 0);
return;
}
static void
{
if (macinfo->llcp_kstatp) {
}
}
/*
* llc1_subs_bind(q, mp)
* implements the DL_SUBS_BIND_REQ primitive
* this only works for a STREAM bound to LLC_SNAP_SAP
* or one bound to the automatic SNAP mode.
* If bound to LLC_SNAP_SAP, the subs bind can be:
* - 2 octets treated as a native byte order short (ethertype)
* - 3 octets treated as a network order byte string (OID part)
* - 5 octets treated as a network order byte string (full SNAP header)
* If bound to an automatic SNAP mode sap, then only the 3 octet
* form is allowed
*/
static int
{
int result;
#if defined(LLC1_DEBUG)
}
#endif
/* we only want to support this for SNAP at present */
} else {
switch (subs->dl_subs_sap_length) {
case 2: /* just the ethertype part */
result = DL_BADADDR;
break;
}
break;
case 3: /* just the OID part */
(LLC_SNAP|LLC_SNAP_OID)) {
result = DL_BADADDR;
break;
}
break;
case 5: /* full SNAP header */
result = DL_BADADDR;
break;
}
break;
}
/* if successful, acknowledge and enter the proper state */
BPRI_MED);
}
sizeof (dl_subs_bind_ack_t) + 5;
5);
}
}
return (result);
}
/*
*
*/
static int
llc1_subs_unbind(void)
{
return (DL_UNSUPPORTED);
}
char *
{
bstr[0],
bstr[1],
bstr[2],
bstr[3],
bstr[4]);
return (buff);
}
static int
{
}