components/python/python26/patches/Python26-11-dlpi.patch
changeset 4984 7145b15b7f0d
parent 4983 db2589571faa
child 4985 eed3576cafd0
equal deleted inserted replaced
4983:db2589571faa 4984:7145b15b7f0d
     1 diff --git Python-2.6.4/Modules/dlpimodule.c Python-2.6.4/Modules/dlpimodule.c
       
     2 new file mode 100644
       
     3 --- /dev/null
       
     4 +++ Python-2.6.4/Modules/dlpimodule.c
       
     5 @@ -0,0 +1,1206 @@
       
     6 +/*
       
     7 + * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     8 + * of this software and associated documentation files (the "Software"), to
       
     9 + * deal in the Software without restriction, including without limitation the
       
    10 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
       
    11 + * sell copies of the Software, and to permit persons to whom the Software is
       
    12 + * furnished to do so, subject to the following conditions:
       
    13 + *
       
    14 + * The above copyright notice and this permission notice shall be included in
       
    15 + * all copies or substantial portions of the Software.
       
    16 + *
       
    17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       
    20 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    21 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
       
    22 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
       
    23 + * DEALINGS IN THE SOFTWARE.
       
    24 + *
       
    25 + * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
       
    26 + * Use is subject to license terms.
       
    27 + */
       
    28 +
       
    29 +#include <Python.h>
       
    30 +#include <stdio.h>
       
    31 +#include <libdlpi.h>
       
    32 +
       
    33 +typedef struct {
       
    34 +	PyObject_HEAD
       
    35 +	dlpi_handle_t dlpihdl;
       
    36 +} pylink_t;
       
    37 +
       
    38 +typedef struct {
       
    39 +	PyObject *pyfunc;
       
    40 +	PyObject *pyarg;
       
    41 +} callback_data_t;
       
    42 +
       
    43 +/*
       
    44 + * dlpi_err: the only exception raised for libdlpi related error.
       
    45 + * The accompanying value is:
       
    46 + * (dlpi_error_number, string), when it's a dlpi specific error,
       
    47 + * or, (DL_SYSERR, errno, string), when it's coming from a system call.
       
    48 + */
       
    49 +static PyObject *dlpi_err;
       
    50 +
       
    51 +static void
       
    52 +dlpi_raise_exception(int err)
       
    53 +{
       
    54 +	PyObject *e = NULL;
       
    55 +
       
    56 +	if (err == DL_SYSERR) {
       
    57 +		e = Py_BuildValue("(iis)", DL_SYSERR, errno, strerror(errno));
       
    58 +	} else {
       
    59 +		e = Py_BuildValue("(is)", err, dlpi_strerror(err));
       
    60 +	}
       
    61 +	if (e != NULL) {
       
    62 +		PyErr_SetObject(dlpi_err, e);
       
    63 +		Py_DECREF(e);
       
    64 +	}
       
    65 +}
       
    66 +
       
    67 +PyDoc_STRVAR(link_doc,
       
    68 +    "link(linkname[, flags]) -> link object\n"
       
    69 +    "\n"
       
    70 +    "Open linkname with specified flags.\n"
       
    71 +    "Three flags are supported: PASSIVE, RAW, NATIVE.\n"
       
    72 +    "And these flags can be bitwise-OR'ed together(default flag is 0).\n"
       
    73 +    "You need sys_net_rawaccess privilege to open a link.\n"
       
    74 +    "See dlpi_open(3DLPI).\n"
       
    75 +);
       
    76 +static int
       
    77 +link_init(PyObject *self, PyObject *args, PyObject *kwds)
       
    78 +{
       
    79 +	uint_t flags = 0;
       
    80 +	dlpi_handle_t dh;
       
    81 +	char *linkname;
       
    82 +	int rval;
       
    83 +	static char *keywords[] = {"linkname", "flags", NULL};
       
    84 +	pylink_t *link = (pylink_t *)self;
       
    85 +
       
    86 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|I", keywords,
       
    87 +	    &linkname, &flags))
       
    88 +		return (-1);
       
    89 +
       
    90 +	if ((rval = dlpi_open(linkname, &dh, flags)) != DLPI_SUCCESS) {
       
    91 +		dlpi_raise_exception(rval);
       
    92 +		return (-1);
       
    93 +	}
       
    94 +
       
    95 +	link->dlpihdl = dh;
       
    96 +
       
    97 +	return (0);
       
    98 +}
       
    99 +
       
   100 +static void
       
   101 +link_dealloc(pylink_t *link)
       
   102 +{
       
   103 +	if (link->dlpihdl != NULL)
       
   104 +		dlpi_close(link->dlpihdl);
       
   105 +	link->ob_type->tp_free((PyObject *)link);
       
   106 +}
       
   107 +
       
   108 +PyDoc_STRVAR(bind_doc,
       
   109 +    "bind(sap) -> unsigned int\n"
       
   110 +    "\n"
       
   111 +    "Attempts to bind the link to specified SAP, or ANY_SAP.\n"
       
   112 +    "Returns the SAP that the function actually bound to, which\n"
       
   113 +    "could be different from the SAP requested.\n"
       
   114 +    "See dlpi_bind(3DLPI).\n"
       
   115 +);
       
   116 +static PyObject *
       
   117 +link_bind(pylink_t *link, PyObject *args, PyObject *kwds)
       
   118 +{
       
   119 +	uint_t sap = 0, boundsap = 0;
       
   120 +	static char *keywords[] = {"sap", NULL};
       
   121 +	int rval;
       
   122 +
       
   123 +	if (link->dlpihdl == NULL) {
       
   124 +		errno = EINVAL;
       
   125 +		dlpi_raise_exception(DL_SYSERR);
       
   126 +		return (NULL);
       
   127 +	}
       
   128 +
       
   129 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &sap))
       
   130 +		return (NULL);
       
   131 +
       
   132 +	if ((rval = dlpi_bind(link->dlpihdl, sap, &boundsap)) !=
       
   133 +	    DLPI_SUCCESS) {
       
   134 +		dlpi_raise_exception(rval);
       
   135 +		return (NULL);
       
   136 +	}
       
   137 +
       
   138 +	return (Py_BuildValue("I", boundsap));
       
   139 +}
       
   140 +
       
   141 +PyDoc_STRVAR(unbind_doc,
       
   142 +    "unbind() -> None\n"
       
   143 +    "\n"
       
   144 +    "Attempts to unbind the link from previously bound sap.\n"
       
   145 +    "See dlpi_unbind(3DLPI).\n"
       
   146 +);
       
   147 +static PyObject *
       
   148 +link_unbind(pylink_t *link)
       
   149 +{
       
   150 +	int rval;
       
   151 +
       
   152 +	if (link->dlpihdl == NULL) {
       
   153 +		errno = EINVAL;
       
   154 +		dlpi_raise_exception(DL_SYSERR);
       
   155 +		return (NULL);
       
   156 +	}
       
   157 +
       
   158 +	if ((rval = dlpi_unbind(link->dlpihdl)) != DLPI_SUCCESS) {
       
   159 +		dlpi_raise_exception(rval);
       
   160 +		return (NULL);
       
   161 +	}
       
   162 +
       
   163 +	Py_INCREF(Py_None);
       
   164 +	return (Py_None);
       
   165 +}
       
   166 +
       
   167 +PyDoc_STRVAR(send_doc,
       
   168 +    "send(destaddr, message[, sap, minpri, maxpri]) -> None\n"
       
   169 +    "\n"
       
   170 +    "Attempts to send message over this link to sap on destaddr.\n"
       
   171 +    "If SAP is not specified, the bound SAP is used\n"
       
   172 +    "You can also specify priority range (minpri, maxpri).\n"
       
   173 +    "See dlpi_send(3DLPI).\n"
       
   174 +);
       
   175 +static PyObject *
       
   176 +link_send(pylink_t *link, PyObject *args, PyObject *kwds)
       
   177 +{
       
   178 +	char *daddr = NULL, *msgbuf = NULL;
       
   179 +	size_t daddrlen = 0, msglen = 0;
       
   180 +	t_scalar_t minpri = DL_QOS_DONT_CARE, maxpri = DL_QOS_DONT_CARE;
       
   181 +	uint_t sap = DLPI_ANY_SAP;
       
   182 +	dlpi_sendinfo_t ds, *dsp = NULL;
       
   183 +	static char *keywords[] =
       
   184 +	    {"destaddr", "message", "sap", "minpri", "maxpri", NULL};
       
   185 +	int rval;
       
   186 +
       
   187 +	if (link->dlpihdl == NULL) {
       
   188 +		errno = EINVAL;
       
   189 +		dlpi_raise_exception(DL_SYSERR);
       
   190 +		return (NULL);
       
   191 +	}
       
   192 +
       
   193 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#s#|Iii", keywords,
       
   194 +	    &daddr, &daddrlen, &msgbuf, &msglen, &sap, &minpri, &maxpri))
       
   195 +		return (NULL);
       
   196 +
       
   197 +	if ((sap != DLPI_ANY_SAP) || (minpri != DL_QOS_DONT_CARE) ||
       
   198 +	    (maxpri != DL_QOS_DONT_CARE)) {
       
   199 +		ds.dsi_sap = sap;
       
   200 +		ds.dsi_prio.dl_min = minpri;
       
   201 +		ds.dsi_prio.dl_max = maxpri;
       
   202 +		dsp = &ds;
       
   203 +	}
       
   204 +
       
   205 +	if ((rval = dlpi_send(link->dlpihdl, daddr, daddrlen,
       
   206 +	    msgbuf, msglen, dsp)) != DLPI_SUCCESS) {
       
   207 +		dlpi_raise_exception(rval);
       
   208 +		return (NULL);
       
   209 +	}
       
   210 +
       
   211 +	Py_INCREF(Py_None);
       
   212 +	return (Py_None);
       
   213 +}
       
   214 +
       
   215 +PyDoc_STRVAR(recv_doc,
       
   216 +    "recv(msglen[, timeout]) -> (string, string), or (None, None)\n"
       
   217 +    "\n"
       
   218 +    "Attempts to receive message over this link.\n"
       
   219 +    "You need to specify the message length for the received message.\n"
       
   220 +    "And you can specify timeout value in milliseconds.\n"
       
   221 +    "The default timeout value is -1 (wait forever).\n"
       
   222 +    "Returns (source address, message data), or (None, None) when error occurs.\n"
       
   223 +    "See dlpi_recv(3DLPI).\n"
       
   224 +);
       
   225 +static PyObject *
       
   226 +link_recv(pylink_t *link, PyObject *args, PyObject *kwds)
       
   227 +{
       
   228 +	PyObject *obj;
       
   229 +	char *saddr = NULL, *msgbuf = NULL;
       
   230 +	size_t saddrlen = 0, msglen = 0, *saddrlenp = NULL, *msglenp = NULL;
       
   231 +	int msec = -1; /* block until receive data */
       
   232 +	static char *keywords[] = {"msglen", "timeout", NULL};
       
   233 +	int rval;
       
   234 +
       
   235 +	if (link->dlpihdl == NULL) {
       
   236 +		errno = EINVAL;
       
   237 +		dlpi_raise_exception(DL_SYSERR);
       
   238 +		return (NULL);
       
   239 +	}
       
   240 +
       
   241 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "k|i",
       
   242 +	    keywords, &msglen, &msec))
       
   243 +		return (NULL);
       
   244 +
       
   245 +	if (msglen > 0) {
       
   246 +		msgbuf = malloc(msglen);
       
   247 +		if (msgbuf == NULL) {
       
   248 +			dlpi_raise_exception(DL_SYSERR);
       
   249 +			return (NULL);
       
   250 +		}
       
   251 +		saddrlen = DLPI_PHYSADDR_MAX;
       
   252 +		saddr = malloc(saddrlen);
       
   253 +		if (saddr == NULL) {
       
   254 +			dlpi_raise_exception(DL_SYSERR);
       
   255 +			free(msgbuf);
       
   256 +			return (NULL);
       
   257 +		}
       
   258 +		msglenp = &msglen;
       
   259 +		saddrlenp = &saddrlen;
       
   260 +	}
       
   261 +
       
   262 +	if ((rval = dlpi_recv(link->dlpihdl, saddr, saddrlenp, msgbuf,
       
   263 +	    msglenp, msec, NULL)) != DLPI_SUCCESS) {
       
   264 +		if (msgbuf != NULL)
       
   265 +			free(msgbuf);
       
   266 +		if (saddr != NULL)
       
   267 +			free(saddr);
       
   268 +		dlpi_raise_exception(rval);
       
   269 +		return (NULL);
       
   270 +	}
       
   271 +
       
   272 +	obj = Py_BuildValue("s#s#", saddr, saddrlen, msgbuf, msglen);
       
   273 +	if (msgbuf != NULL)
       
   274 +		free(msgbuf);
       
   275 +	if (saddr != NULL)
       
   276 +		free(saddr);
       
   277 +	return (obj);
       
   278 +}
       
   279 +
       
   280 +PyDoc_STRVAR(disabmulti_doc,
       
   281 +    "disabmulti(address) -> None\n"
       
   282 +    "\n"
       
   283 +    "Disable a specified multicast address on this link.\n"
       
   284 +    "See dlpi_disabmulti(3DLPI).\n"
       
   285 +);
       
   286 +static PyObject *
       
   287 +link_disabmulti(pylink_t *link, PyObject *args, PyObject *kwds)
       
   288 +{
       
   289 +	char *addr = NULL;
       
   290 +	size_t addrlen = 0;
       
   291 +	static char *keywords[] = {"address", NULL};
       
   292 +	int rval;
       
   293 +
       
   294 +	if (link->dlpihdl == NULL) {
       
   295 +		errno = EINVAL;
       
   296 +		dlpi_raise_exception(DL_SYSERR);
       
   297 +		return (NULL);
       
   298 +	}
       
   299 +
       
   300 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", keywords,
       
   301 +	    &addr, &addrlen))
       
   302 +		return (NULL);
       
   303 +
       
   304 +	if ((addrlen == 0) || (addrlen > DLPI_PHYSADDR_MAX)) {
       
   305 +		errno = EINVAL;
       
   306 +		dlpi_raise_exception(DL_SYSERR);
       
   307 +		return (NULL);
       
   308 +	}
       
   309 +
       
   310 +	if ((rval = dlpi_disabmulti(link->dlpihdl, addr, addrlen)) !=
       
   311 +	    DLPI_SUCCESS) {
       
   312 +		dlpi_raise_exception(rval);
       
   313 +		return (NULL);
       
   314 +	}
       
   315 +
       
   316 +	Py_INCREF(Py_None);
       
   317 +	return (Py_None);
       
   318 +}
       
   319 +
       
   320 +PyDoc_STRVAR(enabmulti_doc,
       
   321 +    "enabmulti(address) -> None\n"
       
   322 +    "\n"
       
   323 +    "Enable a specified multicast address on this link.\n"
       
   324 +    "See dlpi_enabmulti(3DLPI).\n"
       
   325 +);
       
   326 +static PyObject *
       
   327 +link_enabmulti(pylink_t *link, PyObject *args, PyObject *kwds)
       
   328 +{
       
   329 +	char *addr = NULL;
       
   330 +	size_t addrlen = 0;
       
   331 +	static char *keywords[] = {"address", NULL};
       
   332 +	int rval;
       
   333 +
       
   334 +	if (link->dlpihdl == NULL) {
       
   335 +		errno = EINVAL;
       
   336 +		dlpi_raise_exception(DL_SYSERR);
       
   337 +		return (NULL);
       
   338 +	}
       
   339 +
       
   340 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", keywords,
       
   341 +	    &addr, &addrlen))
       
   342 +		return (NULL);
       
   343 +
       
   344 +	if ((addrlen == 0) || (addrlen > DLPI_PHYSADDR_MAX)) {
       
   345 +		errno = EINVAL;
       
   346 +		dlpi_raise_exception(DL_SYSERR);
       
   347 +		return (NULL);
       
   348 +	}
       
   349 +
       
   350 +	if ((rval = dlpi_enabmulti(link->dlpihdl, addr, addrlen)) !=
       
   351 +	    DLPI_SUCCESS) {
       
   352 +		dlpi_raise_exception(rval);
       
   353 +		return (NULL);
       
   354 +	}
       
   355 +
       
   356 +	Py_INCREF(Py_None);
       
   357 +	return (Py_None);
       
   358 +}
       
   359 +
       
   360 +static void
       
   361 +dlpi_callback(dlpi_handle_t hdl, dlpi_notifyinfo_t *ni, void *arg)
       
   362 +{
       
   363 +	callback_data_t *cd = (callback_data_t *)arg;
       
   364 +	PyObject *arglist, *result;
       
   365 +
       
   366 +	switch (ni->dni_note) {
       
   367 +	case DL_NOTE_SPEED:
       
   368 +		arglist = Py_BuildValue("(OII)",
       
   369 +		    cd->pyarg, ni->dni_note, ni->dni_speed);
       
   370 +		break;
       
   371 +	case DL_NOTE_SDU_SIZE:
       
   372 +		arglist = Py_BuildValue("(OII)",
       
   373 +		    cd->pyarg, ni->dni_note, ni->dni_size);
       
   374 +		break;
       
   375 +	case DL_NOTE_PHYS_ADDR:
       
   376 +		arglist = Py_BuildValue("(OIs#)",
       
   377 +		    cd->pyarg, ni->dni_note, ni->dni_physaddr,
       
   378 +		    ni->dni_physaddrlen);
       
   379 +		break;
       
   380 +	default:
       
   381 +		arglist = Py_BuildValue("(OIO)", cd->pyarg, ni->dni_note,
       
   382 +		    Py_None);
       
   383 +	}
       
   384 +
       
   385 +	result = PyEval_CallObject(cd->pyfunc, arglist);
       
   386 +	Py_DECREF(arglist);
       
   387 +	if (result == NULL) {
       
   388 +		PyErr_Clear(); /* cannot raise error */
       
   389 +	}
       
   390 +	Py_DECREF(result);
       
   391 +	Py_DECREF(cd->pyfunc);
       
   392 +	Py_XDECREF(cd->pyarg);
       
   393 +	free(cd);
       
   394 +}
       
   395 +
       
   396 +PyDoc_STRVAR(enabnotify_doc,
       
   397 +    "enabnotify(events, function[, arg]) -> unsigned long\n"
       
   398 +    "\n"
       
   399 +    "Enables a notification callback for the set of specified events,\n"
       
   400 +    "which must be one or more (by a logical OR) events listed as below:\n"
       
   401 +    "NOTE_LINK_DOWN         Notify when link has gone down\n"
       
   402 +    "NOTE_LINK_UP           Notify when link has come up\n"
       
   403 +    "NOTE_PHYS_ADDR         Notify when address changes\n"
       
   404 +    "NOTE_SDU_SIZE          Notify when MTU changes\n"
       
   405 +    "NOTE_SPEED             Notify when speed changes\n"
       
   406 +    "NOTE_PROMISC_ON_PHYS   Notify when PROMISC_PHYS is set\n"
       
   407 +    "NOTE_PROMISC_OFF_PHYS  Notify when PROMISC_PHYS is cleared\n"
       
   408 +    "Returns a handle for this registration.\n"
       
   409 +    "See dlpi_enabnotify(3DLPI).\n"
       
   410 +);
       
   411 +static PyObject *
       
   412 +link_enabnotify(pylink_t *link, PyObject *args, PyObject *kwds)
       
   413 +{
       
   414 +	PyObject *func = NULL, *arg = NULL;
       
   415 +	callback_data_t *cd;
       
   416 +	uint_t notes = 0;
       
   417 +	static char *keywords[] = {"events", "function", "arg", NULL};
       
   418 +	dlpi_notifyid_t id;
       
   419 +	int rval;
       
   420 +
       
   421 +	if (link->dlpihdl == NULL) {
       
   422 +		errno = EINVAL;
       
   423 +		dlpi_raise_exception(DL_SYSERR);
       
   424 +		return (NULL);
       
   425 +	}
       
   426 +
       
   427 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "IO|O",
       
   428 +	    keywords, &notes, &func, &arg))
       
   429 +		return (NULL);
       
   430 +
       
   431 +	if (!PyCallable_Check(func)) {
       
   432 +		errno = EINVAL;
       
   433 +		dlpi_raise_exception(DL_SYSERR);
       
   434 +		return (NULL);
       
   435 +	}
       
   436 +
       
   437 +	cd = malloc(sizeof(callback_data_t));
       
   438 +	if (cd == NULL) {
       
   439 +		dlpi_raise_exception(DL_SYSERR);
       
   440 +		return (NULL);
       
   441 +	}
       
   442 +	Py_INCREF(func);
       
   443 +	Py_XINCREF(arg);
       
   444 +	cd->pyfunc = func;
       
   445 +	cd->pyarg = arg;
       
   446 +
       
   447 +	if ((rval = dlpi_enabnotify(link->dlpihdl, notes, dlpi_callback,
       
   448 +	    cd, &id)) != DLPI_SUCCESS) {
       
   449 +		free(cd);
       
   450 +		Py_DECREF(func);
       
   451 +		Py_XDECREF(arg);
       
   452 +		dlpi_raise_exception(rval);
       
   453 +		return (NULL);
       
   454 +	}
       
   455 +
       
   456 +	return (Py_BuildValue("k", id));
       
   457 +}
       
   458 +
       
   459 +PyDoc_STRVAR(disabnotify_doc,
       
   460 +    "disabnotify(handle) -> argument object, or None\n"
       
   461 +    "\n"
       
   462 +    "Disables the notification registration associated with handle.\n"
       
   463 +    "You should get this handle by calling enabnotify().\n"
       
   464 +    "Returns the argument passed in when registering the callback, or None.\n"
       
   465 +    "See dlpi_disabnotify(3DLPI).\n"
       
   466 +);
       
   467 +static PyObject *
       
   468 +link_disabnotify(pylink_t *link, PyObject *args, PyObject *kwds)
       
   469 +{
       
   470 +	dlpi_notifyid_t id;
       
   471 +	callback_data_t *arg;
       
   472 +	PyObject *pyargsaved;
       
   473 +	static char *keywords[] = {"handle", NULL};
       
   474 +	int rval;
       
   475 +
       
   476 +	if (link->dlpihdl == NULL) {
       
   477 +		errno = EINVAL;
       
   478 +		dlpi_raise_exception(DL_SYSERR);
       
   479 +		return (NULL);
       
   480 +	}
       
   481 +
       
   482 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "k", keywords, &id))
       
   483 +		return (NULL);
       
   484 +
       
   485 +	if ((rval = dlpi_disabnotify(link->dlpihdl, id, (void **)&arg)) !=
       
   486 +	    DLPI_SUCCESS) {
       
   487 +		dlpi_raise_exception(rval);
       
   488 +		return (NULL);
       
   489 +	}
       
   490 +
       
   491 +	/* clean up */
       
   492 +	pyargsaved = arg->pyarg;
       
   493 +	Py_XINCREF(pyargsaved);
       
   494 +	Py_XDECREF(arg->pyarg);
       
   495 +	Py_DECREF(arg->pyfunc);
       
   496 +	free(arg);
       
   497 +
       
   498 +	if (pyargsaved != NULL)
       
   499 +		return (pyargsaved);
       
   500 +
       
   501 +	Py_INCREF(Py_None);
       
   502 +	return (Py_None);
       
   503 +}
       
   504 +
       
   505 +PyDoc_STRVAR(get_sap_doc,
       
   506 +    "get_sap() -> unsigned int\n"
       
   507 +    "\n"
       
   508 +    "Returns the sap bound to this link.\n"
       
   509 +    "See dlpi_info(3DLPI).\n"
       
   510 +);
       
   511 +static PyObject *
       
   512 +link_get_sap(pylink_t *link)
       
   513 +{
       
   514 +	dlpi_info_t info;
       
   515 +	int rval;
       
   516 +
       
   517 +	if (link->dlpihdl == NULL) {
       
   518 +		errno = EINVAL;
       
   519 +		dlpi_raise_exception(DL_SYSERR);
       
   520 +		return (NULL);
       
   521 +	}
       
   522 +
       
   523 +	if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
       
   524 +	    DLPI_SUCCESS) {
       
   525 +		dlpi_raise_exception(rval);
       
   526 +		return (NULL);
       
   527 +	}
       
   528 +
       
   529 +	return (Py_BuildValue("I", info.di_sap));
       
   530 +}
       
   531 +
       
   532 +PyDoc_STRVAR(get_fd_doc,
       
   533 +    "get_fd() -> int\n"
       
   534 +    "\n"
       
   535 +    "Returns the integer file descriptor that can be used to directly\n"
       
   536 +    "operate on the link.\n"
       
   537 +    "See dlpi_fd(3DLPI).\n"
       
   538 +);
       
   539 +static PyObject *
       
   540 +link_get_fd(pylink_t *link)
       
   541 +{
       
   542 +	int fd;
       
   543 +
       
   544 +	if (link->dlpihdl == NULL) {
       
   545 +		errno = EINVAL;
       
   546 +		dlpi_raise_exception(DL_SYSERR);
       
   547 +		return (NULL);
       
   548 +	}
       
   549 +
       
   550 +	if ((fd = dlpi_fd(link->dlpihdl)) == -1) {
       
   551 +		dlpi_raise_exception(DL_SYSERR);
       
   552 +		return (NULL);
       
   553 +	}
       
   554 +
       
   555 +	return (Py_BuildValue("i", fd));
       
   556 +}
       
   557 +
       
   558 +PyDoc_STRVAR(get_linkname_doc,
       
   559 +    "get_linkname() -> string\n"
       
   560 +    "\n"
       
   561 +    "Returns the name of the link.\n"
       
   562 +    "See dlpi_linkname(3DLPI).\n"
       
   563 +);
       
   564 +static PyObject *
       
   565 +link_get_linkname(pylink_t *link)
       
   566 +{
       
   567 +	const char *name = NULL;
       
   568 +
       
   569 +	if (link->dlpihdl == NULL) {
       
   570 +		errno = EINVAL;
       
   571 +		dlpi_raise_exception(DL_SYSERR);
       
   572 +		return (NULL);
       
   573 +	}
       
   574 +
       
   575 +	if ((name = dlpi_linkname(link->dlpihdl)) == NULL) {
       
   576 +		dlpi_raise_exception(DL_SYSERR);
       
   577 +		return (NULL);
       
   578 +	}
       
   579 +
       
   580 +	return (Py_BuildValue("s", name));
       
   581 +}
       
   582 +
       
   583 +PyDoc_STRVAR(get_bcastaddr_doc,
       
   584 +    "get_bcastaddr() -> string, or None\n"
       
   585 +    "\n"
       
   586 +    "Returns the broadcast address of the link.\n"
       
   587 +    "Returns None if the broadcast address is empty.\n"
       
   588 +    "See dlpi_info(3DLPI).\n"
       
   589 +);
       
   590 +static PyObject *
       
   591 +link_get_bcastaddr(pylink_t *link)
       
   592 +{
       
   593 +	char *addr[DLPI_PHYSADDR_MAX];
       
   594 +	size_t addrlen = 0;
       
   595 +	dlpi_info_t info;
       
   596 +	int rval;
       
   597 +
       
   598 +	if (link->dlpihdl == NULL) {
       
   599 +		errno = EINVAL;
       
   600 +		dlpi_raise_exception(DL_SYSERR);
       
   601 +		return (NULL);
       
   602 +	}
       
   603 +
       
   604 +	if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
       
   605 +	    DLPI_SUCCESS) {
       
   606 +		dlpi_raise_exception(rval);
       
   607 +		return (NULL);
       
   608 +	}
       
   609 +
       
   610 +	if (info.di_bcastaddrlen == 0) {
       
   611 +		Py_INCREF(Py_None);
       
   612 +		return (Py_None);
       
   613 +	}
       
   614 +
       
   615 +	return (Py_BuildValue("s#", info.di_bcastaddr, info.di_bcastaddrlen));
       
   616 +}
       
   617 +
       
   618 +PyDoc_STRVAR(get_physaddr_doc,
       
   619 +    "get_physaddr(addrtype) -> string, or None\n"
       
   620 +    "\n"
       
   621 +    "Addrtype can be any one of the value listed below:\n"
       
   622 +    "FACT_PHYS_ADDR    Factory physical address\n"
       
   623 +    "CURR_PHYS_ADDR    Current physical address\n"
       
   624 +    "Returns the corresponding physical address of the link.\n"
       
   625 +    "See dlpi_get_physaddr(3DLPI).\n"
       
   626 +);
       
   627 +static PyObject *
       
   628 +link_get_physaddr(pylink_t *link, PyObject *args, PyObject *kwds)
       
   629 +{
       
   630 +	char *addr[DLPI_PHYSADDR_MAX];
       
   631 +	size_t addrlen = DLPI_PHYSADDR_MAX;
       
   632 +	static char *keywords[] = {"addrtype", NULL};
       
   633 +	uint_t type;
       
   634 +	int rval;
       
   635 +
       
   636 +	if (link->dlpihdl == NULL) {
       
   637 +		errno = EINVAL;
       
   638 +		dlpi_raise_exception(DL_SYSERR);
       
   639 +		return (NULL);
       
   640 +	}
       
   641 +
       
   642 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &type))
       
   643 +		return (NULL);
       
   644 +
       
   645 +	if ((rval = dlpi_get_physaddr(link->dlpihdl, type, addr, &addrlen)) !=
       
   646 +	    DLPI_SUCCESS) {
       
   647 +		dlpi_raise_exception(rval);
       
   648 +		return (NULL);
       
   649 +	}
       
   650 +
       
   651 +	return (Py_BuildValue("s#", addr, addrlen));
       
   652 +}
       
   653 +
       
   654 +PyDoc_STRVAR(set_physaddr_doc,
       
   655 +    "set_physaddr(address) -> None\n"
       
   656 +    "\n"
       
   657 +    "Sets the physical address of the link.\n"
       
   658 +    "See dlpi_set_physaddr(3DLPI).\n"
       
   659 +);
       
   660 +static PyObject *
       
   661 +link_set_physaddr(pylink_t *link, PyObject *args, PyObject *kwds)
       
   662 +{
       
   663 +	char *addr = NULL;
       
   664 +	size_t addrlen = 0;
       
   665 +	static char *keywords[] = {"address", NULL};
       
   666 +	int rval;
       
   667 +
       
   668 +	if (link->dlpihdl == NULL) {
       
   669 +		errno = EINVAL;
       
   670 +		dlpi_raise_exception(DL_SYSERR);
       
   671 +		return (NULL);
       
   672 +	}
       
   673 +
       
   674 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", keywords,
       
   675 +	    &addr, &addrlen))
       
   676 +		return (NULL);
       
   677 +
       
   678 +	if ((rval = dlpi_set_physaddr(link->dlpihdl, DL_CURR_PHYS_ADDR,
       
   679 +	    addr, addrlen)) != DLPI_SUCCESS) {
       
   680 +		dlpi_raise_exception(rval);
       
   681 +		return (NULL);
       
   682 +	}
       
   683 +
       
   684 +	Py_INCREF(Py_None);
       
   685 +	return (Py_None);
       
   686 +}
       
   687 +
       
   688 +PyDoc_STRVAR(promiscon_doc,
       
   689 +    "promiscon([level]) -> None\n"
       
   690 +    "\n"
       
   691 +    "Enables promiscuous mode for the link at levels:\n"
       
   692 +    "PROMISC_PHYS     Promiscuous mode at the physical level(default)\n"
       
   693 +    "PROMISC_SAP      Promiscuous mode at the SAP level\n"
       
   694 +    "PROMISC_MULTI    Promiscuous mode for all multicast addresses\n"
       
   695 +    "See dlpi_promiscon(3DLPI).\n"
       
   696 +);
       
   697 +static PyObject *
       
   698 +link_promiscon(pylink_t *link, PyObject *args, PyObject *kwds)
       
   699 +{
       
   700 +	uint_t level = DL_PROMISC_PHYS;
       
   701 +	static char *keywords[] = {"level", NULL};
       
   702 +	int rval;
       
   703 +
       
   704 +	if (link->dlpihdl == NULL) {
       
   705 +		errno = EINVAL;
       
   706 +		dlpi_raise_exception(DL_SYSERR);
       
   707 +		return (NULL);
       
   708 +	}
       
   709 +
       
   710 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", keywords, &level))
       
   711 +		return (NULL);
       
   712 +
       
   713 +	if ((rval = dlpi_promiscon(link->dlpihdl, level)) != DLPI_SUCCESS) {
       
   714 +		dlpi_raise_exception(rval);
       
   715 +		return (NULL);
       
   716 +	}
       
   717 +
       
   718 +	Py_INCREF(Py_None);
       
   719 +	return (Py_None);
       
   720 +}
       
   721 +
       
   722 +PyDoc_STRVAR(promiscoff_doc,
       
   723 +    "promiscoff([level]) -> None\n"
       
   724 +    "\n"
       
   725 +    "Disables promiscuous mode for the link at levels:\n"
       
   726 +    "PROMISC_PHYS     Promiscuous mode at the physical level(default)\n"
       
   727 +    "PROMISC_SAP      Promiscuous mode at the SAP level\n"
       
   728 +    "PROMISC_MULTI    Promiscuous mode for all multicast addresses\n"
       
   729 +    "See dlpi_promiscoff(3DLPI).\n"
       
   730 +);
       
   731 +static PyObject *
       
   732 +link_promiscoff(pylink_t *link, PyObject *args, PyObject *kwds)
       
   733 +{
       
   734 +	uint_t level = DL_PROMISC_PHYS;
       
   735 +	static char *keywords[] = {"level", NULL};
       
   736 +	int rval;
       
   737 +
       
   738 +	if (link->dlpihdl == NULL) {
       
   739 +		errno = EINVAL;
       
   740 +		dlpi_raise_exception(DL_SYSERR);
       
   741 +		return (NULL);
       
   742 +	}
       
   743 +
       
   744 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", keywords, &level))
       
   745 +		return (NULL);
       
   746 +
       
   747 +	if ((rval = dlpi_promiscoff(link->dlpihdl, level)) != DLPI_SUCCESS) {
       
   748 +		dlpi_raise_exception(rval);
       
   749 +		return (NULL);
       
   750 +	}
       
   751 +
       
   752 +	Py_INCREF(Py_None);
       
   753 +	return (Py_None);
       
   754 +}
       
   755 +
       
   756 +PyDoc_STRVAR(get_timeout_doc,
       
   757 +    "get_timeout() -> int\n"
       
   758 +    "\n"
       
   759 +    "Returns current time out value of the link.\n"
       
   760 +    "See dlpi_info(3DLPI).\n"
       
   761 +);
       
   762 +static PyObject *
       
   763 +link_get_timeout(pylink_t *link)
       
   764 +{
       
   765 +	dlpi_info_t info;
       
   766 +	int rval;
       
   767 +
       
   768 +	if (link->dlpihdl == NULL) {
       
   769 +		errno = EINVAL;
       
   770 +		dlpi_raise_exception(DL_SYSERR);
       
   771 +		return (NULL);
       
   772 +	}
       
   773 +
       
   774 +	if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
       
   775 +	    DLPI_SUCCESS) {
       
   776 +		dlpi_raise_exception(rval);
       
   777 +		return (NULL);
       
   778 +	}
       
   779 +
       
   780 +	return (Py_BuildValue("i", info.di_timeout));
       
   781 +}
       
   782 +
       
   783 +PyDoc_STRVAR(get_mactype_doc,
       
   784 +    "get_mactype() -> unsigned char\n"
       
   785 +    "\n"
       
   786 +    "Returns MAC type of the link.\n"
       
   787 +    "See <sys/dlpi.h> for the list of possible MAC types.\n"
       
   788 +    "See dlpi_info(3DLPI).\n"
       
   789 +);
       
   790 +static PyObject *
       
   791 +link_get_mactype(pylink_t *link)
       
   792 +{
       
   793 +	dlpi_info_t info;
       
   794 +	int rval;
       
   795 +
       
   796 +	if (link->dlpihdl == NULL) {
       
   797 +		errno = EINVAL;
       
   798 +		dlpi_raise_exception(DL_SYSERR);
       
   799 +		return (NULL);
       
   800 +	}
       
   801 +
       
   802 +	if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
       
   803 +	    DLPI_SUCCESS) {
       
   804 +		dlpi_raise_exception(rval);
       
   805 +		return (NULL);
       
   806 +	}
       
   807 +
       
   808 +	return (Py_BuildValue("B", info.di_mactype));
       
   809 +}
       
   810 +
       
   811 +PyDoc_STRVAR(set_timeout_doc,
       
   812 +    "set_timeout(timeout) -> None\n"
       
   813 +    "\n"
       
   814 +    "Sets time out value of the link (default value: DEF_TIMEOUT).\n"
       
   815 +    "See dlpi_set_timeout(3DLPI).\n"
       
   816 +);
       
   817 +static PyObject *
       
   818 +link_set_timeout(pylink_t *link, PyObject *args, PyObject *kwds)
       
   819 +{
       
   820 +	int timeout = DLPI_DEF_TIMEOUT;
       
   821 +	static char *keywords[] = {"timeout", NULL};
       
   822 +	int rval;
       
   823 +
       
   824 +	if (link->dlpihdl == NULL) {
       
   825 +		errno = EINVAL;
       
   826 +		dlpi_raise_exception(DL_SYSERR);
       
   827 +		return (NULL);
       
   828 +	}
       
   829 +
       
   830 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", keywords, &timeout))
       
   831 +		return (NULL);
       
   832 +
       
   833 +	if ((rval = dlpi_set_timeout(link->dlpihdl, timeout)) != DLPI_SUCCESS) {
       
   834 +		dlpi_raise_exception(rval);
       
   835 +		return (NULL);
       
   836 +	}
       
   837 +
       
   838 +	Py_INCREF(Py_None);
       
   839 +	return (Py_None);
       
   840 +}
       
   841 +
       
   842 +PyDoc_STRVAR(get_sdu_doc,
       
   843 +    "get_sdu() -> (unsigned int, unsigned int)\n"
       
   844 +    "\n"
       
   845 +    "Returns (min sdu, max sdu).\n"
       
   846 +    "See dlpi_info(3DLPI).\n"
       
   847 +);
       
   848 +static PyObject *
       
   849 +link_get_sdu(pylink_t *link)
       
   850 +{
       
   851 +	dlpi_info_t info;
       
   852 +	int rval;
       
   853 +
       
   854 +	if (link->dlpihdl == NULL) {
       
   855 +		errno = EINVAL;
       
   856 +		dlpi_raise_exception(DL_SYSERR);
       
   857 +		return (NULL);
       
   858 +	}
       
   859 +
       
   860 +	if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
       
   861 +	    DLPI_SUCCESS) {
       
   862 +		dlpi_raise_exception(rval);
       
   863 +		return (NULL);
       
   864 +	}
       
   865 +
       
   866 +	return (Py_BuildValue("II", info.di_min_sdu, info.di_max_sdu));
       
   867 +}
       
   868 +
       
   869 +PyDoc_STRVAR(get_state_doc,
       
   870 +    "get_state() -> unsigned int\n"
       
   871 +    "\n"
       
   872 +    "Returns current state of the link (either UNBOUND or IDLE).\n"
       
   873 +    "See dlpi_info(3DLPI).\n"
       
   874 +);
       
   875 +static PyObject *
       
   876 +link_get_state(pylink_t *link)
       
   877 +{
       
   878 +	dlpi_info_t info;
       
   879 +	int rval;
       
   880 +
       
   881 +	if (link->dlpihdl == NULL) {
       
   882 +		errno = EINVAL;
       
   883 +		dlpi_raise_exception(DL_SYSERR);
       
   884 +		return (NULL);
       
   885 +	}
       
   886 +
       
   887 +	if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
       
   888 +	    DLPI_SUCCESS) {
       
   889 +		dlpi_raise_exception(rval);
       
   890 +		return (NULL);
       
   891 +	}
       
   892 +
       
   893 +	return (Py_BuildValue("I", info.di_state));
       
   894 +}
       
   895 +
       
   896 +PyDoc_STRVAR(get_qos_select_doc,
       
   897 +    "get_qos_select() -> (unsigned int, int, int, int)\n"
       
   898 +    "\n"
       
   899 +    "Returns (qos type, trans delay, priority, residul err).\n"
       
   900 +    "Unsupported QOS parameters are set to UNKNOWN.\n"
       
   901 +    "See dlpi_info(3DLPI).\n"
       
   902 +);
       
   903 +static PyObject *
       
   904 +link_get_qos_select(pylink_t *link)
       
   905 +{
       
   906 +	dlpi_info_t info;
       
   907 +	int rval;
       
   908 +
       
   909 +	if (link->dlpihdl == NULL) {
       
   910 +		errno = EINVAL;
       
   911 +		dlpi_raise_exception(DL_SYSERR);
       
   912 +		return (NULL);
       
   913 +	}
       
   914 +
       
   915 +	if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
       
   916 +	    DLPI_SUCCESS) {
       
   917 +		dlpi_raise_exception(rval);
       
   918 +		return (NULL);
       
   919 +	}
       
   920 +
       
   921 +	return (Py_BuildValue("Iiiii",
       
   922 +	    info.di_qos_sel.dl_qos_type,
       
   923 +	    info.di_qos_sel.dl_trans_delay,
       
   924 +	    info.di_qos_sel.dl_priority,
       
   925 +	    info.di_qos_sel.dl_residual_error));
       
   926 +}
       
   927 +
       
   928 +PyDoc_STRVAR(get_qos_range_doc,
       
   929 +    "get_qos_range() -> \n"
       
   930 +    "	(unsigned int, (int, int), (int, int), (int, int), int)\n"
       
   931 +    "\n"
       
   932 +    "Returns (qos type, (trans delay target, trans delay accept),\n"
       
   933 +    "(min priority, max priority), (min protection, max protection),\n"
       
   934 +    "residual err).\n"
       
   935 +    "Unsupported QOS range values are set to UNKNOWN.\n"
       
   936 +    "See dlpi_info(3DLPI).\n"
       
   937 +);
       
   938 +static PyObject *
       
   939 +link_get_qos_range(pylink_t *link)
       
   940 +{
       
   941 +	dlpi_info_t info;
       
   942 +	int rval;
       
   943 +
       
   944 +	if (link->dlpihdl == NULL) {
       
   945 +		errno = EINVAL;
       
   946 +		dlpi_raise_exception(DL_SYSERR);
       
   947 +		return (NULL);
       
   948 +	}
       
   949 +
       
   950 +	if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
       
   951 +	    DLPI_SUCCESS) {
       
   952 +		dlpi_raise_exception(rval);
       
   953 +		return (NULL);
       
   954 +	}
       
   955 +
       
   956 +	return (Py_BuildValue("I(ii)(ii)(ii)i",
       
   957 +	    info.di_qos_range.dl_qos_type,
       
   958 +	    info.di_qos_range.dl_trans_delay.dl_target_value,
       
   959 +	    info.di_qos_range.dl_trans_delay.dl_accept_value,
       
   960 +	    info.di_qos_range.dl_priority.dl_min,
       
   961 +	    info.di_qos_range.dl_priority.dl_max,
       
   962 +	    info.di_qos_range.dl_protection.dl_min,
       
   963 +	    info.di_qos_range.dl_protection.dl_max,
       
   964 +	    info.di_qos_range.dl_residual_error));
       
   965 +}
       
   966 +
       
   967 +static PyMethodDef pylink_methods[] = {
       
   968 +	{"bind", (PyCFunction)link_bind, METH_VARARGS|METH_KEYWORDS, bind_doc},
       
   969 +	{"unbind", (PyCFunction)link_unbind, METH_NOARGS, unbind_doc},
       
   970 +	{"send", (PyCFunction)link_send, METH_VARARGS|METH_KEYWORDS,
       
   971 +	    send_doc},
       
   972 +	{"recv", (PyCFunction)link_recv, METH_VARARGS|METH_KEYWORDS,
       
   973 +	    recv_doc},
       
   974 +	{"disabmulti", (PyCFunction)link_disabmulti, METH_VARARGS|METH_KEYWORDS,
       
   975 +	    disabmulti_doc},
       
   976 +	{"enabmulti", (PyCFunction)link_enabmulti, METH_VARARGS|METH_KEYWORDS,
       
   977 +	    enabmulti_doc},
       
   978 +	{"enabnotify", (PyCFunction)link_enabnotify,
       
   979 +	    METH_VARARGS|METH_KEYWORDS, enabnotify_doc},
       
   980 +	{"disabnotify", (PyCFunction)link_disabnotify,
       
   981 +	    METH_VARARGS|METH_KEYWORDS, disabnotify_doc},
       
   982 +	{"get_fd", (PyCFunction)link_get_fd, METH_NOARGS, get_fd_doc},
       
   983 +	{"get_sap", (PyCFunction)link_get_sap, METH_NOARGS, get_sap_doc},
       
   984 +	{"get_mactype", (PyCFunction)link_get_mactype, METH_NOARGS,
       
   985 +	    get_mactype_doc},
       
   986 +	{"get_linkname", (PyCFunction)link_get_linkname, METH_NOARGS,
       
   987 +	    get_linkname_doc},
       
   988 +	{"get_bcastaddr", (PyCFunction)link_get_bcastaddr, METH_NOARGS,
       
   989 +	    get_bcastaddr_doc},
       
   990 +	{"get_physaddr", (PyCFunction)link_get_physaddr,
       
   991 +	    METH_VARARGS|METH_KEYWORDS, get_physaddr_doc},
       
   992 +	{"set_physaddr", (PyCFunction)link_set_physaddr,
       
   993 +	    METH_VARARGS|METH_KEYWORDS, set_physaddr_doc},
       
   994 +	{"promiscon", (PyCFunction)link_promiscon, METH_VARARGS|METH_KEYWORDS,
       
   995 +	    promiscon_doc},
       
   996 +	{"promiscoff", (PyCFunction)link_promiscoff, METH_VARARGS|METH_KEYWORDS,
       
   997 +	    promiscoff_doc},
       
   998 +	{"get_timeout", (PyCFunction)link_get_timeout, METH_NOARGS,
       
   999 +	    get_timeout_doc},
       
  1000 +	{"set_timeout", (PyCFunction)link_set_timeout,
       
  1001 +	    METH_VARARGS|METH_KEYWORDS, set_timeout_doc},
       
  1002 +	{"get_sdu", (PyCFunction)link_get_sdu, METH_NOARGS, get_sdu_doc},
       
  1003 +	{"get_state", (PyCFunction)link_get_state, METH_NOARGS,
       
  1004 +	    get_state_doc},
       
  1005 +	{"get_qos_select", (PyCFunction)link_get_qos_select, METH_NOARGS,
       
  1006 +	    get_qos_select_doc},
       
  1007 +	{"get_qos_range", (PyCFunction)link_get_qos_range, METH_NOARGS,
       
  1008 +	    get_qos_range_doc},
       
  1009 +	{NULL}
       
  1010 +};
       
  1011 +
       
  1012 +static PyTypeObject pylink_type = {
       
  1013 +	PyObject_HEAD_INIT(0)	/* Must fill in type value later */
       
  1014 +	0,					/* ob_size */
       
  1015 +	"dlpi.link",				/* tp_name */
       
  1016 +	sizeof(pylink_t),			/* tp_basicsize */
       
  1017 +	0,					/* tp_itemsize */
       
  1018 +	(destructor)link_dealloc,		/* tp_dealloc */
       
  1019 +	0,					/* tp_print */
       
  1020 +	0,					/* tp_getattr */
       
  1021 +	0,					/* tp_setattr */
       
  1022 +	0,					/* tp_compare */
       
  1023 +	0,					/* tp_repr */
       
  1024 +	0,					/* tp_as_number */
       
  1025 +	0,					/* tp_as_sequence */
       
  1026 +	0,					/* tp_as_mapping */
       
  1027 +	0,					/* tp_hash */
       
  1028 +	0,					/* tp_call */
       
  1029 +	0,					/* tp_str */
       
  1030 +	0,					/* tp_getattro */
       
  1031 +	0,					/* tp_setattro */
       
  1032 +	0,					/* tp_as_buffer */
       
  1033 +	Py_TPFLAGS_DEFAULT,			/* tp_flags */
       
  1034 +	link_doc,				/* tp_doc */
       
  1035 +	0,					/* tp_traverse */
       
  1036 +	0,					/* tp_clear */
       
  1037 +	0,					/* tp_richcompare */
       
  1038 +	0,					/* tp_weaklistoffset */
       
  1039 +	0,					/* tp_iter */
       
  1040 +	0,					/* tp_iternext */
       
  1041 +	pylink_methods,				/* tp_methods */
       
  1042 +	0,					/* tp_members */
       
  1043 +	0,					/* tp_getset */
       
  1044 +	0,					/* tp_base */
       
  1045 +	0,					/* tp_dict */
       
  1046 +	0,					/* tp_descr_get */
       
  1047 +	0,					/* tp_descr_set */
       
  1048 +	0,					/* tp_dictoffset */
       
  1049 +	(initproc)link_init,			/* tp_init */
       
  1050 +	0,					/* tp_alloc */
       
  1051 +	PyType_GenericNew,			/* tp_new */
       
  1052 +	0,					/* tp_free */
       
  1053 +};
       
  1054 +
       
  1055 +PyDoc_STRVAR(arptype_doc,
       
  1056 +    "arptype(arptype) -> unsigned int\n"
       
  1057 +    "\n"
       
  1058 +    "Converts a DLPI MAC type to an ARP hardware type defined\n"
       
  1059 +    " in <netinet/arp.h>\n"
       
  1060 +    "See dlpi_arptype(3DLPI)\n"
       
  1061 +);
       
  1062 +static PyObject *
       
  1063 +arptype(PyObject *dlpi, PyObject *args, PyObject *kwds)
       
  1064 +{
       
  1065 +	static char *keywords[] = {"arptype", NULL};
       
  1066 +	uint_t dlpityp, arptyp;
       
  1067 +
       
  1068 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &dlpityp))
       
  1069 +		return (NULL);
       
  1070 +
       
  1071 +	if ((arptyp = dlpi_arptype(dlpityp)) == 0) {
       
  1072 +		errno = EINVAL;
       
  1073 +		dlpi_raise_exception(DL_SYSERR);
       
  1074 +		return (NULL);
       
  1075 +	}
       
  1076 +
       
  1077 +	return (Py_BuildValue("I", arptyp));
       
  1078 +}
       
  1079 +
       
  1080 +PyDoc_STRVAR(iftype_doc,
       
  1081 +    "iftype(iftype) -> unsigned int\n"
       
  1082 +    "\n"
       
  1083 +    "Converts a DLPI MAC type to a BSD socket interface type\n"
       
  1084 +    "defined in <net/if_types.h>\n"
       
  1085 +    "See dlpi_iftype(3DLPI)\n"
       
  1086 +);
       
  1087 +static PyObject *
       
  1088 +iftype(PyObject *dlpi, PyObject *args, PyObject *kwds)
       
  1089 +{
       
  1090 +	static char *keywords[] = {"iftype", NULL};
       
  1091 +	uint_t dlpityp, iftyp;
       
  1092 +
       
  1093 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &dlpityp))
       
  1094 +		return (NULL);
       
  1095 +
       
  1096 +	if ((iftyp = dlpi_iftype(dlpityp)) == 0) {
       
  1097 +		errno = EINVAL;
       
  1098 +		dlpi_raise_exception(DL_SYSERR);
       
  1099 +		return (NULL);
       
  1100 +	}
       
  1101 +
       
  1102 +	return (Py_BuildValue("I", iftyp));
       
  1103 +}
       
  1104 +
       
  1105 +PyDoc_STRVAR(mactype_doc,
       
  1106 +    "mactype(mactype) -> string\n"
       
  1107 +    "\n"
       
  1108 +    "Returns a string that describes the specified mactype.\n"
       
  1109 +    "Valid mac types are defined in <sys/dlpi.h>.\n"
       
  1110 +    "See dlpi_mactype(3DLPI)\n"
       
  1111 +);
       
  1112 +static PyObject *
       
  1113 +mactype(PyObject *dlpi, PyObject *args, PyObject *kwds)
       
  1114 +{
       
  1115 +	static char *keywords[] = {"mactype", NULL};
       
  1116 +	uint_t mactyp;
       
  1117 +
       
  1118 +	if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &mactyp))
       
  1119 +		return (NULL);
       
  1120 +
       
  1121 +	return (Py_BuildValue("s", dlpi_mactype(mactyp)));
       
  1122 +}
       
  1123 +
       
  1124 +static boolean_t
       
  1125 +link_walker(const char *name, void *arg)
       
  1126 +{
       
  1127 +	PyObject *linkname;
       
  1128 +	PyObject *list = (PyObject *)arg;
       
  1129 +
       
  1130 +	if ((list == NULL) || !PyList_Check(list))
       
  1131 +		return (B_FALSE);
       
  1132 +
       
  1133 +	linkname = Py_BuildValue("s", name);
       
  1134 +	if (PyList_Append(list, linkname) == -1)
       
  1135 +		return (B_TRUE);
       
  1136 +
       
  1137 +	Py_DECREF(linkname);
       
  1138 +	return (B_FALSE);
       
  1139 +}
       
  1140 +
       
  1141 +PyDoc_STRVAR(listlink_doc,
       
  1142 +    "listlink() -> list\n"
       
  1143 +    "\n"
       
  1144 +    "Returns a list containing link names of all links on the system.\n"
       
  1145 +);
       
  1146 +static PyObject *
       
  1147 +listlink(PyObject *dlpi)
       
  1148 +{
       
  1149 +	PyObject *list;
       
  1150 +
       
  1151 +	if ((list = PyList_New(0)) == NULL)
       
  1152 +		return (NULL);
       
  1153 +
       
  1154 +	dlpi_walk(link_walker, list, 0);
       
  1155 +	return (list);
       
  1156 +}
       
  1157 +
       
  1158 +static PyMethodDef dlpi_methods[] = {
       
  1159 +	{"arptype", (PyCFunction)arptype, METH_VARARGS|METH_KEYWORDS,
       
  1160 +	    arptype_doc},
       
  1161 +	{"iftype", (PyCFunction)iftype, METH_VARARGS|METH_KEYWORDS,
       
  1162 +	    iftype_doc},
       
  1163 +	{"mactype", (PyCFunction)mactype, METH_VARARGS|METH_KEYWORDS,
       
  1164 +	    mactype_doc},
       
  1165 +	{"listlink", (PyCFunction)listlink, METH_NOARGS, listlink_doc},
       
  1166 +	{NULL}
       
  1167 +};
       
  1168 +
       
  1169 +PyMODINIT_FUNC
       
  1170 +initdlpi(void)
       
  1171 +{
       
  1172 +	PyObject *mod;
       
  1173 +
       
  1174 +	if (PyType_Ready(&pylink_type) < 0)
       
  1175 +		return;
       
  1176 +
       
  1177 +	mod = Py_InitModule("dlpi", dlpi_methods);
       
  1178 +	if (mod == NULL)
       
  1179 +		return;
       
  1180 +
       
  1181 +	dlpi_err = PyErr_NewException("dlpi.error", NULL, NULL);
       
  1182 +	if (dlpi_err == NULL)
       
  1183 +		return;
       
  1184 +	PyModule_AddObject(mod, "error", dlpi_err);
       
  1185 +
       
  1186 +	Py_INCREF(&pylink_type);
       
  1187 +	PyModule_AddObject(mod, "link", (PyObject *)&pylink_type);
       
  1188 +	PyModule_AddIntConstant(mod, "PASSIVE", DLPI_PASSIVE);
       
  1189 +	PyModule_AddIntConstant(mod, "RAW", DLPI_RAW);
       
  1190 +	PyModule_AddIntConstant(mod, "NATIVE", DLPI_NATIVE);
       
  1191 +	PyModule_AddIntConstant(mod, "ANY_SAP", DLPI_ANY_SAP);
       
  1192 +	PyModule_AddIntConstant(mod, "DEF_TIMEOUT", DLPI_DEF_TIMEOUT);
       
  1193 +	PyModule_AddIntConstant(mod, "NOTE_LINK_DOWN", DL_NOTE_LINK_DOWN);
       
  1194 +	PyModule_AddIntConstant(mod, "NOTE_LINK_UP", DL_NOTE_LINK_UP);
       
  1195 +	PyModule_AddIntConstant(mod, "NOTE_PHYS_ADDR", DL_NOTE_PHYS_ADDR);
       
  1196 +	PyModule_AddIntConstant(mod, "NOTE_SDU_SIZE", DL_NOTE_SDU_SIZE);
       
  1197 +	PyModule_AddIntConstant(mod, "NOTE_SPEED", DL_NOTE_SPEED);
       
  1198 +	PyModule_AddIntConstant(mod, "NOTE_PROMISC_ON_PHYS",
       
  1199 +	    DL_NOTE_PROMISC_ON_PHYS);
       
  1200 +	PyModule_AddIntConstant(mod, "NOTE_PROMISC_OFF_PHYS",
       
  1201 +	    DL_NOTE_PROMISC_OFF_PHYS);
       
  1202 +	PyModule_AddIntConstant(mod, "FACT_PHYS_ADDR", DL_FACT_PHYS_ADDR);
       
  1203 +	PyModule_AddIntConstant(mod, "CURR_PHYS_ADDR", DL_CURR_PHYS_ADDR);
       
  1204 +	PyModule_AddIntConstant(mod, "PROMISC_PHYS", DL_PROMISC_PHYS);
       
  1205 +	PyModule_AddIntConstant(mod, "PROMISC_SAP", DL_PROMISC_SAP);
       
  1206 +	PyModule_AddIntConstant(mod, "PROMISC_MULTI", DL_PROMISC_MULTI);
       
  1207 +	PyModule_AddIntConstant(mod, "UNKNOWN", DL_UNKNOWN);
       
  1208 +	PyModule_AddIntConstant(mod, "UNBOUND", DL_UNBOUND);
       
  1209 +	PyModule_AddIntConstant(mod, "IDLE", DL_IDLE);
       
  1210 +	PyModule_AddIntConstant(mod, "SYSERR", DL_SYSERR);
       
  1211 +}
       
  1212 diff --git Python-2.6.4/setup.py Python-2.6.4/setup.py
       
  1213 --- Python-2.6.4/setup.py
       
  1214 +++ Python-2.6.4/setup.py
       
  1215 @@ -1284,6 +1284,12 @@
       
  1216              exts.append( Extension('ucred', ['ucred.c'],
       
  1217                                     libraries = ['tsol']) )
       
  1218  
       
  1219 +        # dlpi module (Solaris)
       
  1220 +        dlpi_inc = find_file('libdlpi.h', [], inc_dirs)
       
  1221 +        if dlpi_inc is not None:
       
  1222 +            exts.append( Extension('dlpi', ['dlpimodule.c'],
       
  1223 +                                   libraries = ['dlpi']) )
       
  1224 +
       
  1225          # Thomas Heller's _ctypes module
       
  1226          self.detect_ctypes(inc_dirs, lib_dirs)
       
  1227  
       
  1228 diff --git Python-2.6.4/lib/test/dlpitest.py Python-2.6.4/Lib/test/dlpitest.py
       
  1229 new file mode 100644
       
  1230 --- /dev/null	2011-02-12 03:13:26.000000000 -0600
       
  1231 +++ Python-2.6.4/Lib/test/dlpitest.py	2011-01-20 13:52:42.895865414 -0600
       
  1232 @@ -0,0 +1,96 @@
       
  1233 +#!/usr/bin/python2.6
       
  1234 +
       
  1235 +import dlpi
       
  1236 +import sys
       
  1237 +import time
       
  1238 +import struct
       
  1239 +
       
  1240 +#test listlink
       
  1241 +linklist = dlpi.listlink()
       
  1242 +print "Found %d links:" % len(linklist)
       
  1243 +print linklist
       
  1244 +
       
  1245 +#pick up the first data link for below testing
       
  1246 +linkname = linklist[0]
       
  1247 +
       
  1248 +#open link
       
  1249 +print "opening link: " + linkname + "..."
       
  1250 +testlink = dlpi.link(linkname)
       
  1251 +
       
  1252 +#read some info of testlink
       
  1253 +print "linkname is %s" % testlink.get_linkname()
       
  1254 +print "link fd is %d" % testlink.get_fd()
       
  1255 +mactype = testlink.get_mactype()
       
  1256 +print "dlpi mactype is %d" % mactype
       
  1257 +print "after convert:"
       
  1258 +print "\tmactype is %s" % dlpi.mactype(mactype)
       
  1259 +print "\tiftype is %d" % dlpi.iftype(mactype)
       
  1260 +print "\tarptype is %d" % dlpi.arptype(mactype)
       
  1261 +bcastaddr = testlink.get_bcastaddr()
       
  1262 +print "broadcast addr is: ",
       
  1263 +print struct.unpack("BBBBBB",bcastaddr)
       
  1264 +physaddr = testlink.get_physaddr(dlpi.FACT_PHYS_ADDR)
       
  1265 +print "factory physical address is: ",
       
  1266 +print struct.unpack("BBBBBB",physaddr)
       
  1267 +print "current timeout value is %d" % testlink.get_timeout()
       
  1268 +print "sdu is:",
       
  1269 +print testlink.get_sdu()
       
  1270 +print "qos select is:",
       
  1271 +print testlink.get_qos_select()
       
  1272 +print "qos range is:",
       
  1273 +print testlink.get_qos_range()
       
  1274 +
       
  1275 +#set some config value of testlink and read them again
       
  1276 +print "setting current physiacal addr to aa:0:10:13:27:5"
       
  1277 +testlink.set_physaddr('\xaa\0\x10\x13\x27\5')
       
  1278 +physaddr = testlink.get_physaddr(dlpi.CURR_PHYS_ADDR)
       
  1279 +print "current physical addr is: ",
       
  1280 +print struct.unpack("BBBBBB",physaddr)
       
  1281 +print "set timeout value to 6..."
       
  1282 +testlink.set_timeout(6)
       
  1283 +print "timeout value is %d" % testlink.get_timeout()
       
  1284 +
       
  1285 +#test enable/disable multicast
       
  1286 +print "enable/disable multicast address 1:0:5e:0:0:5"
       
  1287 +testlink.enabmulti('\1\0\x5e\0\0\5')
       
  1288 +testlink.disabmulti('\1\0\x5e\0\0\5')
       
  1289 +
       
  1290 +#test bind
       
  1291 +print "binding to SAP 0x9000..."
       
  1292 +testlink.bind(0x9000)
       
  1293 +print "sap is %x" % testlink.get_sap()
       
  1294 +print "state is: %d"  % testlink.get_state()
       
  1295 +
       
  1296 +#test send
       
  1297 +print "sending broadcast loopback packet..."
       
  1298 +testlink.send(bcastaddr, '\0\1\2\3\4\5')
       
  1299 +
       
  1300 +#test notify functionality
       
  1301 +arg = "notification callback arg"
       
  1302 +def notify(arg, notes, value):
       
  1303 +	print "NOTE_PROMISC_ON_PHYS notification received with arg: '%s'" % arg
       
  1304 +print "enabled notification on NOTE_PROMISC_ON_PHYS"
       
  1305 +id = testlink.enabnotify(dlpi.NOTE_PROMISC_ON_PHYS, notify, arg) #enable notification
       
  1306 +testlink.promiscon() #trigger the event (will be seen while receiving pkt below)
       
  1307 +
       
  1308 +#test receive
       
  1309 +print "testing receiving..."
       
  1310 +try:
       
  1311 +	testlink.recv(0, 0) #should see NOTE_PROMISC_ON_PHYS event here
       
  1312 +except dlpi.error, err:
       
  1313 +	errnum, errinfo = err
       
  1314 +	if errnum == 10006:
       
  1315 +		pass #timeout error is expected here
       
  1316 +	else: #test fails if reach here
       
  1317 +		print "test failed",
       
  1318 +		print errnum,
       
  1319 +		print err
       
  1320 +
       
  1321 +testlink.promiscoff()
       
  1322 +testlink.disabnotify(id) #disable notification
       
  1323 +
       
  1324 +#test unbind
       
  1325 +print "unbinding..."
       
  1326 +testlink.unbind()
       
  1327 +print "sap is %x" % testlink.get_sap()
       
  1328 +print "state is: %d"  % testlink.get_state()