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()