1 This patch provides Python dlpi support. It may be contributed upstream at
2 some point, but the suitability (or lack thereof) has not yet been determined.
3 --- Python-3.9.1/Modules/dlpimodule.c
4 +++ Python-3.9.1/Modules/dlpimodule.c
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:
14 + * The above copyright notice and this permission notice shall be included in
15 + * all copies or substantial portions of the Software.
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.
25 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
34 + dlpi_handle_t dlpihdl;
43 + * dlpi_err: the only exception raised for libdlpi related error.
44 + * The accompanying value is:
45 + * (dlpi_error_number, string), when it's a dlpi specific error,
46 + * or, (DL_SYSERR, errno, string), when it's coming from a system call.
48 +static PyObject *dlpi_err;
51 +dlpi_raise_exception(int err)
55 + if (err == DL_SYSERR) {
56 + e = Py_BuildValue("(iis)", DL_SYSERR, errno, strerror(errno));
58 + e = Py_BuildValue("(is)", err, dlpi_strerror(err));
61 + PyErr_SetObject(dlpi_err, e);
66 +PyDoc_STRVAR(link_doc,
67 + "link(linkname[, flags]) -> link object\n"
69 + "Open linkname with specified flags.\n"
70 + "Three flags are supported: PASSIVE, RAW, NATIVE.\n"
71 + "And these flags can be bitwise-OR'ed together(default flag is 0).\n"
72 + "You need sys_net_rawaccess privilege to open a link.\n"
73 + "See dlpi_open(3DLPI).\n"
76 +link_init(PyObject *self, PyObject *args, PyObject *kwds)
82 + static char *keywords[] = {"linkname", "flags", NULL};
83 + pylink_t *link = (pylink_t *)self;
85 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|I", keywords,
89 + if ((rval = dlpi_open(linkname, &dh, flags)) != DLPI_SUCCESS) {
90 + dlpi_raise_exception(rval);
100 +link_dealloc(pylink_t *link)
102 + if (link->dlpihdl != NULL)
103 + dlpi_close(link->dlpihdl);
104 + Py_TYPE(link)->tp_free((PyObject *)link);
107 +PyDoc_STRVAR(bind_doc,
108 + "bind(sap) -> unsigned int\n"
110 + "Attempts to bind the link to specified SAP, or ANY_SAP.\n"
111 + "Returns the SAP that the function actually bound to, which\n"
112 + "could be different from the SAP requested.\n"
113 + "See dlpi_bind(3DLPI).\n"
116 +link_bind(pylink_t *link, PyObject *args, PyObject *kwds)
118 + uint_t sap = 0, boundsap = 0;
119 + static char *keywords[] = {"sap", NULL};
122 + if (link->dlpihdl == NULL) {
124 + dlpi_raise_exception(DL_SYSERR);
128 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &sap))
131 + if ((rval = dlpi_bind(link->dlpihdl, sap, &boundsap)) !=
133 + dlpi_raise_exception(rval);
137 + return (Py_BuildValue("I", boundsap));
140 +PyDoc_STRVAR(unbind_doc,
141 + "unbind() -> None\n"
143 + "Attempts to unbind the link from previously bound sap.\n"
144 + "See dlpi_unbind(3DLPI).\n"
147 +link_unbind(pylink_t *link)
151 + if (link->dlpihdl == NULL) {
153 + dlpi_raise_exception(DL_SYSERR);
157 + if ((rval = dlpi_unbind(link->dlpihdl)) != DLPI_SUCCESS) {
158 + dlpi_raise_exception(rval);
162 + Py_INCREF(Py_None);
166 +PyDoc_STRVAR(send_doc,
167 + "send(destaddr, message[, sap, minpri, maxpri]) -> None\n"
169 + "Attempts to send message over this link to sap on destaddr.\n"
170 + "If SAP is not specified, the bound SAP is used\n"
171 + "You can also specify priority range (minpri, maxpri).\n"
172 + "See dlpi_send(3DLPI).\n"
175 +link_send(pylink_t *link, PyObject *args, PyObject *kwds)
177 + char *daddr = NULL, *msgbuf = NULL;
178 + size_t daddrlen = 0, msglen = 0;
179 + t_scalar_t minpri = DL_QOS_DONT_CARE, maxpri = DL_QOS_DONT_CARE;
180 + uint_t sap = DLPI_ANY_SAP;
181 + dlpi_sendinfo_t ds, *dsp = NULL;
182 + static char *keywords[] =
183 + {"destaddr", "message", "sap", "minpri", "maxpri", NULL};
186 + if (link->dlpihdl == NULL) {
188 + dlpi_raise_exception(DL_SYSERR);
192 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#s#|Iii", keywords,
193 + &daddr, &daddrlen, &msgbuf, &msglen, &sap, &minpri, &maxpri))
196 + if ((sap != DLPI_ANY_SAP) || (minpri != DL_QOS_DONT_CARE) ||
197 + (maxpri != DL_QOS_DONT_CARE)) {
199 + ds.dsi_prio.dl_min = minpri;
200 + ds.dsi_prio.dl_max = maxpri;
204 + if ((rval = dlpi_send(link->dlpihdl, daddr, daddrlen,
205 + msgbuf, msglen, dsp)) != DLPI_SUCCESS) {
206 + dlpi_raise_exception(rval);
210 + Py_INCREF(Py_None);
214 +PyDoc_STRVAR(recv_doc,
215 + "recv(msglen[, timeout]) -> (string, string), or (None, None)\n"
217 + "Attempts to receive message over this link.\n"
218 + "You need to specify the message length for the received message.\n"
219 + "And you can specify timeout value in milliseconds.\n"
220 + "The default timeout value is -1 (wait forever).\n"
221 + "Returns (source address, message data), or (None, None) when error occurs.\n"
222 + "See dlpi_recv(3DLPI).\n"
225 +link_recv(pylink_t *link, PyObject *args, PyObject *kwds)
228 + char *saddr = NULL, *msgbuf = NULL;
229 + size_t saddrlen = 0, msglen = 0, *saddrlenp = NULL, *msglenp = NULL;
230 + int msec = -1; /* block until receive data */
231 + static char *keywords[] = {"msglen", "timeout", NULL};
234 + if (link->dlpihdl == NULL) {
236 + dlpi_raise_exception(DL_SYSERR);
240 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "k|i",
241 + keywords, &msglen, &msec))
245 + msgbuf = malloc(msglen);
246 + if (msgbuf == NULL) {
247 + dlpi_raise_exception(DL_SYSERR);
250 + saddrlen = DLPI_PHYSADDR_MAX;
251 + saddr = malloc(saddrlen);
252 + if (saddr == NULL) {
253 + dlpi_raise_exception(DL_SYSERR);
258 + saddrlenp = &saddrlen;
261 + if ((rval = dlpi_recv(link->dlpihdl, saddr, saddrlenp, msgbuf,
262 + msglenp, msec, NULL)) != DLPI_SUCCESS) {
263 + if (msgbuf != NULL)
267 + dlpi_raise_exception(rval);
271 + obj = Py_BuildValue("s#s#", saddr, saddrlen, msgbuf, msglen);
272 + if (msgbuf != NULL)
279 +PyDoc_STRVAR(disabmulti_doc,
280 + "disabmulti(address) -> None\n"
282 + "Disable a specified multicast address on this link.\n"
283 + "See dlpi_disabmulti(3DLPI).\n"
286 +link_disabmulti(pylink_t *link, PyObject *args, PyObject *kwds)
289 + size_t addrlen = 0;
290 + static char *keywords[] = {"address", NULL};
293 + if (link->dlpihdl == NULL) {
295 + dlpi_raise_exception(DL_SYSERR);
299 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", keywords,
303 + if ((addrlen == 0) || (addrlen > DLPI_PHYSADDR_MAX)) {
305 + dlpi_raise_exception(DL_SYSERR);
309 + if ((rval = dlpi_disabmulti(link->dlpihdl, addr, addrlen)) !=
311 + dlpi_raise_exception(rval);
315 + Py_INCREF(Py_None);
319 +PyDoc_STRVAR(enabmulti_doc,
320 + "enabmulti(address) -> None\n"
322 + "Enable a specified multicast address on this link.\n"
323 + "See dlpi_enabmulti(3DLPI).\n"
326 +link_enabmulti(pylink_t *link, PyObject *args, PyObject *kwds)
329 + size_t addrlen = 0;
330 + static char *keywords[] = {"address", NULL};
333 + if (link->dlpihdl == NULL) {
335 + dlpi_raise_exception(DL_SYSERR);
339 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", keywords,
343 + if ((addrlen == 0) || (addrlen > DLPI_PHYSADDR_MAX)) {
345 + dlpi_raise_exception(DL_SYSERR);
349 + if ((rval = dlpi_enabmulti(link->dlpihdl, addr, addrlen)) !=
351 + dlpi_raise_exception(rval);
355 + Py_INCREF(Py_None);
360 +dlpi_callback(dlpi_handle_t hdl, dlpi_notifyinfo_t *ni, void *arg)
362 + callback_data_t *cd = (callback_data_t *)arg;
363 + PyObject *arglist, *result;
365 + switch (ni->dni_note) {
366 + case DL_NOTE_SPEED:
367 + arglist = Py_BuildValue("(OII)",
368 + cd->pyarg, ni->dni_note, ni->dni_speed);
370 + case DL_NOTE_SDU_SIZE:
371 + arglist = Py_BuildValue("(OII)",
372 + cd->pyarg, ni->dni_note, ni->dni_size);
374 + case DL_NOTE_PHYS_ADDR:
375 + arglist = Py_BuildValue("(OIs#)",
376 + cd->pyarg, ni->dni_note, ni->dni_physaddr,
377 + ni->dni_physaddrlen);
380 + arglist = Py_BuildValue("(OIO)", cd->pyarg, ni->dni_note,
384 + result = PyEval_CallObject(cd->pyfunc, arglist);
385 + Py_DECREF(arglist);
386 + if (result == NULL) {
387 + PyErr_Clear(); /* cannot raise error */
390 + Py_DECREF(cd->pyfunc);
391 + Py_XDECREF(cd->pyarg);
395 +PyDoc_STRVAR(enabnotify_doc,
396 + "enabnotify(events, function[, arg]) -> unsigned long\n"
398 + "Enables a notification callback for the set of specified events,\n"
399 + "which must be one or more (by a logical OR) events listed as below:\n"
400 + "NOTE_LINK_DOWN Notify when link has gone down\n"
401 + "NOTE_LINK_UP Notify when link has come up\n"
402 + "NOTE_PHYS_ADDR Notify when address changes\n"
403 + "NOTE_SDU_SIZE Notify when MTU changes\n"
404 + "NOTE_SPEED Notify when speed changes\n"
405 + "NOTE_PROMISC_ON_PHYS Notify when PROMISC_PHYS is set\n"
406 + "NOTE_PROMISC_OFF_PHYS Notify when PROMISC_PHYS is cleared\n"
407 + "Returns a handle for this registration.\n"
408 + "See dlpi_enabnotify(3DLPI).\n"
411 +link_enabnotify(pylink_t *link, PyObject *args, PyObject *kwds)
413 + PyObject *func = NULL, *arg = NULL;
414 + callback_data_t *cd;
416 + static char *keywords[] = {"events", "function", "arg", NULL};
417 + dlpi_notifyid_t id;
420 + if (link->dlpihdl == NULL) {
422 + dlpi_raise_exception(DL_SYSERR);
426 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "IO|O",
427 + keywords, ¬es, &func, &arg))
430 + if (!PyCallable_Check(func)) {
432 + dlpi_raise_exception(DL_SYSERR);
436 + cd = malloc(sizeof(callback_data_t));
438 + dlpi_raise_exception(DL_SYSERR);
446 + if ((rval = dlpi_enabnotify(link->dlpihdl, notes, dlpi_callback,
447 + cd, &id)) != DLPI_SUCCESS) {
451 + dlpi_raise_exception(rval);
455 + return (Py_BuildValue("k", id));
458 +PyDoc_STRVAR(disabnotify_doc,
459 + "disabnotify(handle) -> argument object, or None\n"
461 + "Disables the notification registration associated with handle.\n"
462 + "You should get this handle by calling enabnotify().\n"
463 + "Returns the argument passed in when registering the callback, or None.\n"
464 + "See dlpi_disabnotify(3DLPI).\n"
467 +link_disabnotify(pylink_t *link, PyObject *args, PyObject *kwds)
469 + dlpi_notifyid_t id;
470 + callback_data_t *arg;
471 + PyObject *pyargsaved;
472 + static char *keywords[] = {"handle", NULL};
475 + if (link->dlpihdl == NULL) {
477 + dlpi_raise_exception(DL_SYSERR);
481 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "k", keywords, &id))
484 + if ((rval = dlpi_disabnotify(link->dlpihdl, id, (void **)&arg)) !=
486 + dlpi_raise_exception(rval);
491 + pyargsaved = arg->pyarg;
492 + Py_XINCREF(pyargsaved);
493 + Py_XDECREF(arg->pyarg);
494 + Py_DECREF(arg->pyfunc);
497 + if (pyargsaved != NULL)
498 + return (pyargsaved);
500 + Py_INCREF(Py_None);
504 +PyDoc_STRVAR(get_sap_doc,
505 + "get_sap() -> unsigned int\n"
507 + "Returns the sap bound to this link.\n"
508 + "See dlpi_info(3DLPI).\n"
511 +link_get_sap(pylink_t *link)
516 + if (link->dlpihdl == NULL) {
518 + dlpi_raise_exception(DL_SYSERR);
522 + if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
524 + dlpi_raise_exception(rval);
528 + return (Py_BuildValue("I", info.di_sap));
531 +PyDoc_STRVAR(get_fd_doc,
532 + "get_fd() -> int\n"
534 + "Returns the integer file descriptor that can be used to directly\n"
535 + "operate on the link.\n"
536 + "See dlpi_fd(3DLPI).\n"
539 +link_get_fd(pylink_t *link)
543 + if (link->dlpihdl == NULL) {
545 + dlpi_raise_exception(DL_SYSERR);
549 + if ((fd = dlpi_fd(link->dlpihdl)) == -1) {
550 + dlpi_raise_exception(DL_SYSERR);
554 + return (Py_BuildValue("i", fd));
557 +PyDoc_STRVAR(get_linkname_doc,
558 + "get_linkname() -> string\n"
560 + "Returns the name of the link.\n"
561 + "See dlpi_linkname(3DLPI).\n"
564 +link_get_linkname(pylink_t *link)
566 + const char *name = NULL;
568 + if (link->dlpihdl == NULL) {
570 + dlpi_raise_exception(DL_SYSERR);
574 + if ((name = dlpi_linkname(link->dlpihdl)) == NULL) {
575 + dlpi_raise_exception(DL_SYSERR);
579 + return (Py_BuildValue("s", name));
582 +PyDoc_STRVAR(get_bcastaddr_doc,
583 + "get_bcastaddr() -> string, or None\n"
585 + "Returns the broadcast address of the link.\n"
586 + "Returns None if the broadcast address is empty.\n"
587 + "See dlpi_info(3DLPI).\n"
590 +link_get_bcastaddr(pylink_t *link)
592 + char *addr[DLPI_PHYSADDR_MAX];
593 + size_t addrlen = 0;
597 + if (link->dlpihdl == NULL) {
599 + dlpi_raise_exception(DL_SYSERR);
603 + if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
605 + dlpi_raise_exception(rval);
609 + if (info.di_bcastaddrlen == 0) {
610 + Py_INCREF(Py_None);
614 + return (Py_BuildValue("s#", info.di_bcastaddr, info.di_bcastaddrlen));
617 +PyDoc_STRVAR(get_physaddr_doc,
618 + "get_physaddr(addrtype) -> string, or None\n"
620 + "Addrtype can be any one of the value listed below:\n"
621 + "FACT_PHYS_ADDR Factory physical address\n"
622 + "CURR_PHYS_ADDR Current physical address\n"
623 + "Returns the corresponding physical address of the link.\n"
624 + "See dlpi_get_physaddr(3DLPI).\n"
627 +link_get_physaddr(pylink_t *link, PyObject *args, PyObject *kwds)
629 + char *addr[DLPI_PHYSADDR_MAX];
630 + size_t addrlen = DLPI_PHYSADDR_MAX;
631 + static char *keywords[] = {"addrtype", NULL};
635 + if (link->dlpihdl == NULL) {
637 + dlpi_raise_exception(DL_SYSERR);
641 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &type))
644 + if ((rval = dlpi_get_physaddr(link->dlpihdl, type, addr, &addrlen)) !=
646 + dlpi_raise_exception(rval);
650 + return (Py_BuildValue("s#", addr, addrlen));
653 +PyDoc_STRVAR(set_physaddr_doc,
654 + "set_physaddr(address) -> None\n"
656 + "Sets the physical address of the link.\n"
657 + "See dlpi_set_physaddr(3DLPI).\n"
660 +link_set_physaddr(pylink_t *link, PyObject *args, PyObject *kwds)
663 + size_t addrlen = 0;
664 + static char *keywords[] = {"address", NULL};
667 + if (link->dlpihdl == NULL) {
669 + dlpi_raise_exception(DL_SYSERR);
673 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", keywords,
677 + if ((rval = dlpi_set_physaddr(link->dlpihdl, DL_CURR_PHYS_ADDR,
678 + addr, addrlen)) != DLPI_SUCCESS) {
679 + dlpi_raise_exception(rval);
683 + Py_INCREF(Py_None);
687 +PyDoc_STRVAR(promiscon_doc,
688 + "promiscon([level]) -> None\n"
690 + "Enables promiscuous mode for the link at levels:\n"
691 + "PROMISC_PHYS Promiscuous mode at the physical level(default)\n"
692 + "PROMISC_SAP Promiscuous mode at the SAP level\n"
693 + "PROMISC_MULTI Promiscuous mode for all multicast addresses\n"
695 + "The level modifier (OR'd with level) is:\n"
696 + "PROMISC_NOLOOP Do not loopback messages to the client (Solaris only)\n"
697 + "See dlpi_promiscon(3DLPI).\n"
700 +link_promiscon(pylink_t *link, PyObject *args, PyObject *kwds)
702 + uint_t level = DL_PROMISC_PHYS;
703 + static char *keywords[] = {"level", NULL};
706 + if (link->dlpihdl == NULL) {
708 + dlpi_raise_exception(DL_SYSERR);
712 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", keywords, &level))
715 + if ((rval = dlpi_promiscon(link->dlpihdl, level)) != DLPI_SUCCESS) {
716 + dlpi_raise_exception(rval);
720 + Py_INCREF(Py_None);
724 +PyDoc_STRVAR(promiscoff_doc,
725 + "promiscoff([level]) -> None\n"
727 + "Disables promiscuous mode for the link at levels:\n"
728 + "PROMISC_PHYS Promiscuous mode at the physical level(default)\n"
729 + "PROMISC_SAP Promiscuous mode at the SAP level\n"
730 + "PROMISC_MULTI Promiscuous mode for all multicast addresses\n"
732 + "The level modifier (OR'd with level) is:\n"
733 + "PROMISC_NOLOOP Do not loopback messages to the client (Solaris only)\n"
734 + "See dlpi_promiscoff(3DLPI).\n"
737 +link_promiscoff(pylink_t *link, PyObject *args, PyObject *kwds)
739 + uint_t level = DL_PROMISC_PHYS;
740 + static char *keywords[] = {"level", NULL};
743 + if (link->dlpihdl == NULL) {
745 + dlpi_raise_exception(DL_SYSERR);
749 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|I", keywords, &level))
752 + if ((rval = dlpi_promiscoff(link->dlpihdl, level)) != DLPI_SUCCESS) {
753 + dlpi_raise_exception(rval);
757 + Py_INCREF(Py_None);
761 +PyDoc_STRVAR(get_timeout_doc,
762 + "get_timeout() -> int\n"
764 + "Returns current time out value of the link.\n"
765 + "See dlpi_info(3DLPI).\n"
768 +link_get_timeout(pylink_t *link)
773 + if (link->dlpihdl == NULL) {
775 + dlpi_raise_exception(DL_SYSERR);
779 + if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
781 + dlpi_raise_exception(rval);
785 + return (Py_BuildValue("i", info.di_timeout));
788 +PyDoc_STRVAR(get_mactype_doc,
789 + "get_mactype() -> unsigned char\n"
791 + "Returns MAC type of the link.\n"
792 + "See <sys/dlpi.h> for the list of possible MAC types.\n"
793 + "See dlpi_info(3DLPI).\n"
796 +link_get_mactype(pylink_t *link)
801 + if (link->dlpihdl == NULL) {
803 + dlpi_raise_exception(DL_SYSERR);
807 + if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
809 + dlpi_raise_exception(rval);
813 + return (Py_BuildValue("B", info.di_mactype));
816 +PyDoc_STRVAR(set_timeout_doc,
817 + "set_timeout(timeout) -> None\n"
819 + "Sets time out value of the link (default value: DEF_TIMEOUT).\n"
820 + "See dlpi_set_timeout(3DLPI).\n"
823 +link_set_timeout(pylink_t *link, PyObject *args, PyObject *kwds)
825 + int timeout = DLPI_DEF_TIMEOUT;
826 + static char *keywords[] = {"timeout", NULL};
829 + if (link->dlpihdl == NULL) {
831 + dlpi_raise_exception(DL_SYSERR);
835 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", keywords, &timeout))
838 + if ((rval = dlpi_set_timeout(link->dlpihdl, timeout)) != DLPI_SUCCESS) {
839 + dlpi_raise_exception(rval);
843 + Py_INCREF(Py_None);
847 +PyDoc_STRVAR(get_sdu_doc,
848 + "get_sdu() -> (unsigned int, unsigned int)\n"
850 + "Returns (min sdu, max sdu).\n"
851 + "See dlpi_info(3DLPI).\n"
854 +link_get_sdu(pylink_t *link)
859 + if (link->dlpihdl == NULL) {
861 + dlpi_raise_exception(DL_SYSERR);
865 + if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
867 + dlpi_raise_exception(rval);
871 + return (Py_BuildValue("II", info.di_min_sdu, info.di_max_sdu));
874 +PyDoc_STRVAR(get_state_doc,
875 + "get_state() -> unsigned int\n"
877 + "Returns current state of the link (either UNBOUND or IDLE).\n"
878 + "See dlpi_info(3DLPI).\n"
881 +link_get_state(pylink_t *link)
886 + if (link->dlpihdl == NULL) {
888 + dlpi_raise_exception(DL_SYSERR);
892 + if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
894 + dlpi_raise_exception(rval);
898 + return (Py_BuildValue("I", info.di_state));
901 +PyDoc_STRVAR(get_qos_select_doc,
902 + "get_qos_select() -> (unsigned int, int, int, int)\n"
904 + "Returns (qos type, trans delay, priority, residul err).\n"
905 + "Unsupported QOS parameters are set to UNKNOWN.\n"
906 + "See dlpi_info(3DLPI).\n"
909 +link_get_qos_select(pylink_t *link)
914 + if (link->dlpihdl == NULL) {
916 + dlpi_raise_exception(DL_SYSERR);
920 + if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
922 + dlpi_raise_exception(rval);
926 + return (Py_BuildValue("Iiiii",
927 + info.di_qos_sel.dl_qos_type,
928 + info.di_qos_sel.dl_trans_delay,
929 + info.di_qos_sel.dl_priority,
930 + info.di_qos_sel.dl_residual_error));
933 +PyDoc_STRVAR(get_qos_range_doc,
934 + "get_qos_range() -> \n"
935 + " (unsigned int, (int, int), (int, int), (int, int), int)\n"
937 + "Returns (qos type, (trans delay target, trans delay accept),\n"
938 + "(min priority, max priority), (min protection, max protection),\n"
940 + "Unsupported QOS range values are set to UNKNOWN.\n"
941 + "See dlpi_info(3DLPI).\n"
944 +link_get_qos_range(pylink_t *link)
949 + if (link->dlpihdl == NULL) {
951 + dlpi_raise_exception(DL_SYSERR);
955 + if ((rval = dlpi_info(link->dlpihdl, &info, 0)) !=
957 + dlpi_raise_exception(rval);
961 + return (Py_BuildValue("I(ii)(ii)(ii)i",
962 + info.di_qos_range.dl_qos_type,
963 + info.di_qos_range.dl_trans_delay.dl_target_value,
964 + info.di_qos_range.dl_trans_delay.dl_accept_value,
965 + info.di_qos_range.dl_priority.dl_min,
966 + info.di_qos_range.dl_priority.dl_max,
967 + info.di_qos_range.dl_protection.dl_min,
968 + info.di_qos_range.dl_protection.dl_max,
969 + info.di_qos_range.dl_residual_error));
972 +static PyMethodDef pylink_methods[] = {
973 + {"bind", (PyCFunction)link_bind, METH_VARARGS|METH_KEYWORDS, bind_doc},
974 + {"unbind", (PyCFunction)link_unbind, METH_NOARGS, unbind_doc},
975 + {"send", (PyCFunction)link_send, METH_VARARGS|METH_KEYWORDS,
977 + {"recv", (PyCFunction)link_recv, METH_VARARGS|METH_KEYWORDS,
979 + {"disabmulti", (PyCFunction)link_disabmulti, METH_VARARGS|METH_KEYWORDS,
981 + {"enabmulti", (PyCFunction)link_enabmulti, METH_VARARGS|METH_KEYWORDS,
983 + {"enabnotify", (PyCFunction)link_enabnotify,
984 + METH_VARARGS|METH_KEYWORDS, enabnotify_doc},
985 + {"disabnotify", (PyCFunction)link_disabnotify,
986 + METH_VARARGS|METH_KEYWORDS, disabnotify_doc},
987 + {"get_fd", (PyCFunction)link_get_fd, METH_NOARGS, get_fd_doc},
988 + {"get_sap", (PyCFunction)link_get_sap, METH_NOARGS, get_sap_doc},
989 + {"get_mactype", (PyCFunction)link_get_mactype, METH_NOARGS,
991 + {"get_linkname", (PyCFunction)link_get_linkname, METH_NOARGS,
993 + {"get_bcastaddr", (PyCFunction)link_get_bcastaddr, METH_NOARGS,
994 + get_bcastaddr_doc},
995 + {"get_physaddr", (PyCFunction)link_get_physaddr,
996 + METH_VARARGS|METH_KEYWORDS, get_physaddr_doc},
997 + {"set_physaddr", (PyCFunction)link_set_physaddr,
998 + METH_VARARGS|METH_KEYWORDS, set_physaddr_doc},
999 + {"promiscon", (PyCFunction)link_promiscon, METH_VARARGS|METH_KEYWORDS,
1001 + {"promiscoff", (PyCFunction)link_promiscoff, METH_VARARGS|METH_KEYWORDS,
1003 + {"get_timeout", (PyCFunction)link_get_timeout, METH_NOARGS,
1005 + {"set_timeout", (PyCFunction)link_set_timeout,
1006 + METH_VARARGS|METH_KEYWORDS, set_timeout_doc},
1007 + {"get_sdu", (PyCFunction)link_get_sdu, METH_NOARGS, get_sdu_doc},
1008 + {"get_state", (PyCFunction)link_get_state, METH_NOARGS,
1010 + {"get_qos_select", (PyCFunction)link_get_qos_select, METH_NOARGS,
1011 + get_qos_select_doc},
1012 + {"get_qos_range", (PyCFunction)link_get_qos_range, METH_NOARGS,
1013 + get_qos_range_doc},
1017 +static PyTypeObject pylink_type = {
1018 + PyVarObject_HEAD_INIT(NULL, 0) /* Must fill in type value later */
1019 + "dlpi.link", /* tp_name */
1020 + sizeof(pylink_t), /* tp_basicsize */
1021 + 0, /* tp_itemsize */
1022 + (destructor)link_dealloc, /* tp_dealloc */
1024 + 0, /* tp_getattr */
1025 + 0, /* tp_setattr */
1026 + 0, /* tp_reserved */
1028 + 0, /* tp_as_number */
1029 + 0, /* tp_as_sequence */
1030 + 0, /* tp_as_mapping */
1034 + 0, /* tp_getattro */
1035 + 0, /* tp_setattro */
1036 + 0, /* tp_as_buffer */
1037 + Py_TPFLAGS_DEFAULT, /* tp_flags */
1038 + link_doc, /* tp_doc */
1039 + 0, /* tp_traverse */
1041 + 0, /* tp_richcompare */
1042 + 0, /* tp_weaklistoffset */
1044 + 0, /* tp_iternext */
1045 + pylink_methods, /* tp_methods */
1046 + 0, /* tp_members */
1047 + 0, /* tp_getset */
1050 + 0, /* tp_descr_get */
1051 + 0, /* tp_descr_set */
1052 + 0, /* tp_dictoffset */
1053 + (initproc)link_init, /* tp_init */
1055 + PyType_GenericNew, /* tp_new */
1060 +PyDoc_STRVAR(arptype_doc,
1061 + "arptype(arptype) -> unsigned int\n"
1063 + "Converts a DLPI MAC type to an ARP hardware type defined\n"
1064 + " in <netinet/arp.h>\n"
1065 + "See dlpi_arptype(3DLPI)\n"
1068 +arptype(PyObject *dlpi, PyObject *args, PyObject *kwds)
1070 + static char *keywords[] = {"arptype", NULL};
1071 + uint_t dlpityp, arptyp;
1073 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &dlpityp))
1076 + if ((arptyp = dlpi_arptype(dlpityp)) == 0) {
1078 + dlpi_raise_exception(DL_SYSERR);
1082 + return (Py_BuildValue("I", arptyp));
1085 +PyDoc_STRVAR(iftype_doc,
1086 + "iftype(iftype) -> unsigned int\n"
1088 + "Converts a DLPI MAC type to a BSD socket interface type\n"
1089 + "defined in <net/if_types.h>\n"
1090 + "See dlpi_iftype(3DLPI)\n"
1093 +iftype(PyObject *dlpi, PyObject *args, PyObject *kwds)
1095 + static char *keywords[] = {"iftype", NULL};
1096 + uint_t dlpityp, iftyp;
1098 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &dlpityp))
1101 + if ((iftyp = dlpi_iftype(dlpityp)) == 0) {
1103 + dlpi_raise_exception(DL_SYSERR);
1107 + return (Py_BuildValue("I", iftyp));
1110 +PyDoc_STRVAR(mactype_doc,
1111 + "mactype(mactype) -> string\n"
1113 + "Returns a string that describes the specified mactype.\n"
1114 + "Valid mac types are defined in <sys/dlpi.h>.\n"
1115 + "See dlpi_mactype(3DLPI)\n"
1118 +mactype(PyObject *dlpi, PyObject *args, PyObject *kwds)
1120 + static char *keywords[] = {"mactype", NULL};
1123 + if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", keywords, &mactyp))
1126 + return (Py_BuildValue("s", dlpi_mactype(mactyp)));
1130 +link_walker(const char *name, void *arg)
1132 + PyObject *linkname;
1133 + PyObject *list = (PyObject *)arg;
1135 + if ((list == NULL) || !PyList_Check(list))
1136 + return (_B_FALSE);
1138 + linkname = Py_BuildValue("s", name);
1139 + if (PyList_Append(list, linkname) == -1)
1142 + Py_DECREF(linkname);
1143 + return (_B_FALSE);
1146 +PyDoc_STRVAR(listlink_doc,
1147 + "listlink() -> list\n"
1149 + "Returns a list containing link names of all links on the system.\n"
1152 +listlink(PyObject *dlpi)
1156 + if ((list = PyList_New(0)) == NULL)
1159 + dlpi_walk(link_walker, list, 0);
1163 +static PyMethodDef dlpi_methods[] = {
1164 + {"arptype", (PyCFunction)arptype, METH_VARARGS|METH_KEYWORDS,
1166 + {"iftype", (PyCFunction)iftype, METH_VARARGS|METH_KEYWORDS,
1168 + {"mactype", (PyCFunction)mactype, METH_VARARGS|METH_KEYWORDS,
1170 + {"listlink", (PyCFunction)listlink, METH_NOARGS, listlink_doc},
1179 + if (PyType_Ready(&pylink_type) < 0)
1182 + static struct PyModuleDef moduledef = {
1183 + PyModuleDef_HEAD_INIT,
1194 + mod = PyModule_Create(&moduledef);
1198 + dlpi_err = PyErr_NewException("dlpi.error", NULL, NULL);
1199 + if (dlpi_err == NULL)
1201 + PyModule_AddObject(mod, "error", dlpi_err);
1203 + Py_INCREF(&pylink_type);
1204 + PyModule_AddObject(mod, "link", (PyObject *)&pylink_type);
1205 + PyModule_AddIntConstant(mod, "PASSIVE", DLPI_PASSIVE);
1206 + PyModule_AddIntConstant(mod, "RAW", DLPI_RAW);
1207 + PyModule_AddIntConstant(mod, "NATIVE", DLPI_NATIVE);
1208 + PyModule_AddIntConstant(mod, "ANY_SAP", DLPI_ANY_SAP);
1209 + PyModule_AddIntConstant(mod, "DEF_TIMEOUT", DLPI_DEF_TIMEOUT);
1210 + PyModule_AddIntConstant(mod, "NOTE_LINK_DOWN", DL_NOTE_LINK_DOWN);
1211 + PyModule_AddIntConstant(mod, "NOTE_LINK_UP", DL_NOTE_LINK_UP);
1212 + PyModule_AddIntConstant(mod, "NOTE_PHYS_ADDR", DL_NOTE_PHYS_ADDR);
1213 + PyModule_AddIntConstant(mod, "NOTE_SDU_SIZE", DL_NOTE_SDU_SIZE);
1214 + PyModule_AddIntConstant(mod, "NOTE_SPEED", DL_NOTE_SPEED);
1215 + PyModule_AddIntConstant(mod, "NOTE_PROMISC_ON_PHYS",
1216 + DL_NOTE_PROMISC_ON_PHYS);
1217 + PyModule_AddIntConstant(mod, "NOTE_PROMISC_OFF_PHYS",
1218 + DL_NOTE_PROMISC_OFF_PHYS);
1219 + PyModule_AddIntConstant(mod, "FACT_PHYS_ADDR", DL_FACT_PHYS_ADDR);
1220 + PyModule_AddIntConstant(mod, "CURR_PHYS_ADDR", DL_CURR_PHYS_ADDR);
1221 + PyModule_AddIntConstant(mod, "PROMISC_PHYS", DL_PROMISC_PHYS);
1222 + PyModule_AddIntConstant(mod, "PROMISC_SAP", DL_PROMISC_SAP);
1223 + PyModule_AddIntConstant(mod, "PROMISC_MULTI", DL_PROMISC_MULTI);
1224 + /* Not in illumos: PyModule_AddIntConstant(mod, "PROMISC_NOLOOP", DL_PROMISC_NOLOOP); */
1225 + PyModule_AddIntConstant(mod, "UNKNOWN", DL_UNKNOWN);
1226 + PyModule_AddIntConstant(mod, "UNBOUND", DL_UNBOUND);
1227 + PyModule_AddIntConstant(mod, "IDLE", DL_IDLE);
1228 + PyModule_AddIntConstant(mod, "SYSERR", DL_SYSERR);
1232 --- Python-3.9.1/setup.py
1233 +++ Python-3.9.1/setup.py
1234 @@ -1821,6 +1821,12 @@ class PyBuildExt(build_ext):
1235 if ucred_inc is not None and tsol_inc is not None:
1236 self.add(Extension('ucred', ['ucred.c'], libraries=['tsol']))
1238 + def detect_dlpi(self):
1239 + # dlpi module (Solaris)
1240 + dlpi_inc = find_file('libdlpi.h', [], self.inc_dirs)
1241 + if dlpi_inc is not None:
1242 + self.add(Extension('dlpi', ['dlpimodule.c'], libraries=['dlpi']))
1244 def detect_modules(self):
1245 self.configure_compiler()
1246 self.init_inc_lib_dirs()
1247 @@ -1842,6 +1848,7 @@ class PyBuildExt(build_ext):
1248 self.detect_multibytecodecs()
1249 self.detect_decimal()
1251 + self.detect_dlpi()
1252 self.detect_ctypes()
1253 self.detect_multiprocessing()
1254 if not self.detect_tkinter():
1255 --- Python-3.9.1/Lib/test/dlpitest.py
1256 +++ Python-3.9.1/Lib/test/dlpitest.py
1258 +#!/usr/bin/python3.7
1266 +linklist = dlpi.listlink()
1267 +print("Found %d links:" % len(linklist))
1270 +#pick up the first data link for below testing
1271 +linkname = linklist[0]
1274 +print("opening link: " + linkname + "...")
1275 +testlink = dlpi.link(linkname)
1277 +#read some info of testlink
1278 +print("linkname is %s" % testlink.get_linkname())
1279 +print("link fd is %d" % testlink.get_fd())
1280 +mactype = testlink.get_mactype()
1281 +print("dlpi mactype is %d" % mactype)
1282 +print("after convert:")
1283 +print("\tmactype is %s" % dlpi.mactype(mactype))
1284 +print("\tiftype is %d" % dlpi.iftype(mactype))
1285 +print("\tarptype is %d" % dlpi.arptype(mactype))
1286 +bcastaddr = testlink.get_bcastaddr()
1287 +print("broadcast addr is: ", end=' ')
1288 +print(struct.unpack("BBBBBB",bcastaddr))
1289 +physaddr = testlink.get_physaddr(dlpi.FACT_PHYS_ADDR)
1290 +print("factory physical address is: ", end=' ')
1291 +print(struct.unpack("BBBBBB",physaddr))
1292 +print("current timeout value is %d" % testlink.get_timeout())
1293 +print("sdu is:", end=' ')
1294 +print(testlink.get_sdu())
1295 +print("qos select is:", end=' ')
1296 +print(testlink.get_qos_select())
1297 +print("qos range is:", end=' ')
1298 +print(testlink.get_qos_range())
1300 +#set some config value of testlink and read them again
1301 +print("setting current physiacal addr to aa:0:10:13:27:5")
1302 +testlink.set_physaddr('\xaa\0\x10\x13\x27\5')
1303 +physaddr = testlink.get_physaddr(dlpi.CURR_PHYS_ADDR)
1304 +print("current physical addr is: ", end=' ')
1305 +print(struct.unpack("BBBBBB",physaddr))
1306 +print("set timeout value to 6...")
1307 +testlink.set_timeout(6)
1308 +print("timeout value is %d" % testlink.get_timeout())
1310 +#test enable/disable multicast
1311 +print("enable/disable multicast address 1:0:5e:0:0:5")
1312 +testlink.enabmulti('\1\0\x5e\0\0\5')
1313 +testlink.disabmulti('\1\0\x5e\0\0\5')
1316 +print("binding to SAP 0x9000...")
1317 +testlink.bind(0x9000)
1318 +print("sap is %x" % testlink.get_sap())
1319 +print("state is: %d" % testlink.get_state())
1322 +print("sending broadcast loopback packet...")
1323 +testlink.send(bcastaddr, '\0\1\2\3\4\5')
1325 +#test notify functionality
1326 +arg = "notification callback arg"
1327 +def notify(arg, notes, value):
1328 + print("NOTE_PROMISC_ON_PHYS notification received with arg: '%s'" % arg)
1329 +print("enabled notification on NOTE_PROMISC_ON_PHYS")
1330 +id = testlink.enabnotify(dlpi.NOTE_PROMISC_ON_PHYS, notify, arg) #enable notification
1331 +testlink.promiscon() #trigger the event (will be seen while receiving pkt below)
1334 +print("testing receiving...")
1336 + testlink.recv(0, 0) #should see NOTE_PROMISC_ON_PHYS event here
1337 +except dlpi.error as err:
1338 + errnum, errinfo = err
1339 + if errnum == 10006:
1340 + pass #timeout error is expected here
1341 + else: #test fails if reach here
1342 + print("test failed", end=' ')
1343 + print(errnum, end=' ')
1346 +testlink.promiscoff()
1347 +testlink.disabnotify(id) #disable notification
1350 +print("unbinding...")
1352 +print("sap is %x" % testlink.get_sap())
1353 +print("state is: %d" % testlink.get_state())