diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-04-27 23:21:54 -0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-04-27 23:21:54 -0300 |
commit | 5dfa29b8fad63541499e7ab9de03d280107e1e3e (patch) | |
tree | 77f97e677bc00602f36cd662682c2484881ca14a | |
download | python-inet_diag-5dfa29b8fad63541499e7ab9de03d280107e1e3e.tar.gz |
initial repository
Comes with a barebones ss clone!
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | COPYING | 339 | ||||
-rw-r--r-- | MANIFEST | 8 | ||||
-rw-r--r-- | Makefile | 26 | ||||
-rw-r--r-- | pss.py | 143 | ||||
-rw-r--r-- | python-inet_diag/inet_diag.c | 467 | ||||
-rw-r--r-- | python-inet_diag/inet_diag_copy.h | 123 | ||||
-rw-r--r-- | rpm/SPECS/python-inet_diag.spec | 45 | ||||
-rw-r--r-- | setup.py | 15 |
8 files changed, 1166 insertions, 0 deletions
@@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..fed2b55 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,8 @@ +COPYING +pss.py +python-inet_diag/inet_diag_copy.h +python-inet_diag/inet_diag.c +setup.py +rpm/SPECS/python-inet_diag.spec +MANIFEST +Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0d206ac --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +PACKAGE := python-inet_diag +VERSION := $(shell rpm -q --qf '%{VERSION} ' --specfile rpm/SPECS/$(PACKAGE).spec | cut -d' ' -f1) + +rpmdirs: + @[ -d rpm/BUILD ] || mkdir rpm/BUILD + @[ -d rpm/RPMS ] || mkdir rpm/RPMS + @[ -d rpm/SRPMS ] || mkdir rpm/SRPMS + @[ -d rpm/SOURCES ] || mkdir rpm/SOURCES + +bz2: rpmdirs + git archive --format=tar --prefix=$(PACKAGE)-$(VERSION)/ HEAD | \ + bzip2 -9 > rpm/SOURCES/$(PACKAGE)-$(VERSION).tar.bz2 + +install: + python setup.py install --root=$(DESTDIR) + +rpm: bz2 rpmdirs + rpmbuild -ba --define "_topdir $(PWD)/rpm" rpm/SPECS/$(PACKAGE).spec + +bz2dev: rpmdirs + @mkdir -p /tmp/$(PACKAGE)-$(VERSION) + @tar cf - `cat MANIFEST` | (cd /tmp/$(PACKAGE)-$(VERSION) ; tar xf -) + @(cd /tmp; tar cf - $(PACKAGE)-$(VERSION)) | bzip2 -9 > rpm/SOURCES/$(PACKAGE)-$(VERSION).tar.bz2 + +rpmdev: bz2dev rpmdirs + rpmbuild -ba --define "_topdir $(PWD)/rpm" rpm/SPECS/$(PACKAGE).spec @@ -0,0 +1,143 @@ +#! /usr/bin/python +# -*- python -*- +# -*- coding: utf-8 -*- +# Copyright (C) 2009 Red Hat Inc. +# Written by Arnaldo Carvalho de Melo <acme@redhat.com> +# +# This application is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2. +# +# This application is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +import getopt, inet_diag, sys + +version="0.1" + +def not_implemented(o): + print "%s not implemented yet" % o + +state_width = 10 +addr_width = 40 + +def print_sockets(): + idiag = inet_diag.create() + while True: + try: + s = idiag.get() + except: + break + #print s + #continue + print "%-*s %-6d %-6d %*s:%-5d %*s:%-5d" % \ + (state_width, s.state(), + s.receive_queue(), s.write_queue(), + addr_width, s.saddr(), s.sport(), + addr_width, s.daddr(), s.dport()) + +def usage(): + print '''Usage: ss [ OPTIONS ] + ss [ OPTIONS ] [ FILTER ] + -h, --help this message + -V, --version output version information + -n, --numeric don't resolve service names + -r, --resolve resolve host names + -a, --all display all sockets + -l, --listening display listening sockets + -o, --options show timer information + -e, --extended show detailed socket information + -m, --memory show socket memory usage + -p, --processes show process using socket + -i, --info show internal TCP information + -s, --summary show socket usage summary + + -4, --ipv4 display only IP version 4 sockets + -6, --ipv6 display only IP version 6 sockets + -0, --packet display PACKET sockets + -t, --tcp display only TCP sockets + -u, --udp display only UDP sockets + -d, --dccp display only DCCP sockets + -w, --raw display only RAW sockets + -x, --unix display only Unix domain sockets + -f, --family=FAMILY display sockets of type FAMILY + + -A, --query=QUERY + QUERY := {all|inet|tcp|udp|raw|unix|packet|netlink}[,QUERY] + + -F, --filter=FILE read filter information from FILE + FILTER := [ state TCP-STATE ] [ EXPRESSION ]''' + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], + "hVnraloempis460tudwxf:A:F:", + ("help", "version", "numeric", + "resolve", "all", "listening", + "options", "extended", + "memory", "processes", "info", + "summary", "ipv4", "ipv6", + "packet", "tcp", "udp", + "dccp", "raw", "unix", + "family=", "query=", + "filter=")) + except getopt.GetoptError, err: + usage() + print str(err) + sys.exit(2) + + if not opts: + print_sockets() + sys.exit(0) + + for o, a in opts: + if o in ( "-V", "--version"): + print version + elif o in ( "-n", "--numeric"): + not_implemented(o) + elif o in ( "-r", "--resolve"): + not_implemented(o) + elif o in ( "-a", "--all"): + not_implemented(o) + elif o in ( "-l", "--listening"): + not_implemented(o) + elif o in ( "-o", "--options"): + not_implemented(o) + elif o in ( "-e", "--extended"): + not_implemented(o) + elif o in ( "-m", "--memory"): + not_implemented(o) + elif o in ( "-p", "--processes"): + not_implemented(o) + elif o in ( "-i", "--info"): + not_implemented(o) + elif o in ( "-s", "--summary"): + not_implemented(o) + elif o in ( "-4", "--ipv4"): + not_implemented(o) + elif o in ( "-6", "--ipv6"): + not_implemented(o) + elif o in ( "-0", "--packet"): + not_implemented(o) + elif o in ( "-t", "--tcp"): + not_implemented(o) + elif o in ( "-u", "--udp"): + not_implemented(o) + elif o in ( "-d", "--dccp"): + not_implemented(o) + elif o in ( "-w", "--raw"): + not_implemented(o) + elif o in ( "-x", "--unix"): + not_implemented(o) + elif o in ( "-f", "--family"): + not_implemented(o) + elif o in ( "-A", "--query"): + not_implemented(o) + else: + usage() + return + +if __name__ == '__main__': + main() diff --git a/python-inet_diag/inet_diag.c b/python-inet_diag/inet_diag.c new file mode 100644 index 0000000..c8bd2d8 --- /dev/null +++ b/python-inet_diag/inet_diag.c @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2009 Red Hat Inc. + * + * Arnaldo Carvalho de Melo <acme@redhat.com> + * + * Using code from the iproute2 package which was written mostly by: + * + * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> + * + * This application is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; version 2. + * + * This application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +#include <Python.h> + +#include <errno.h> +#include <sys/socket.h> +#include <linux/netlink.h> +#include <arpa/inet.h> +#include "inet_diag_copy.h" + +#ifndef __unused +#define __unused __attribute__ ((unused)) +#endif + +enum { + TCP_DB, + DCCP_DB, + UDP_DB, + RAW_DB, + UNIX_DG_DB, + UNIX_ST_DB, + PACKET_DG_DB, + PACKET_R_DB, + NETLINK_DB, + MAX_DB +}; + +enum { + SS_UNKNOWN, + SS_ESTABLISHED, + SS_SYN_SENT, + SS_SYN_RECV, + SS_FIN_WAIT1, + SS_FIN_WAIT2, + SS_TIME_WAIT, + SS_CLOSE, + SS_CLOSE_WAIT, + SS_LAST_ACK, + SS_LISTEN, + SS_CLOSING, + SS_MAX +}; + +static const char *sstate_name[] = { + "UNKNOWN", + [SS_ESTABLISHED] = "ESTAB", + [SS_SYN_SENT] = "SYN-SENT", + [SS_SYN_RECV] = "SYN-RECV", + [SS_FIN_WAIT1] = "FIN-WAIT-1", + [SS_FIN_WAIT2] = "FIN-WAIT-2", + [SS_TIME_WAIT] = "TIME-WAIT", + [SS_CLOSE] = "UNCONN", + [SS_CLOSE_WAIT] = "CLOSE-WAIT", + [SS_LAST_ACK] = "LAST-ACK", + [SS_LISTEN] = "LISTEN", + [SS_CLOSING] = "CLOSING", +}; + +#define SS_ALL ((1 << SS_MAX) - 1) + +static int default_states = SS_ALL & ~((1 << SS_LISTEN) | + (1 << SS_CLOSE) | + (1 << SS_TIME_WAIT) | + (1 << SS_SYN_RECV)); + +struct inet_socket { + PyObject_HEAD + struct inet_diag_msg msg; +}; + +/* destructor */ +static void inet_socket__dealloc(struct inet_socket *self) +{ + PyObject_Del(self); +} + +/* prints query object in human readable format */ +static int inet_socket__print(struct inet_socket *self, FILE *fp, + int flags __unused) +{ + char bufsaddr[1024]; + char bufdaddr[1024]; + inet_ntop(self->msg.idiag_family, &self->msg.id.idiag_src, + bufsaddr, sizeof(bufsaddr)); + inet_ntop(self->msg.idiag_family, &self->msg.id.idiag_dst, + bufdaddr, sizeof(bufdaddr)); + fprintf(fp, "<inet_socket state=%s rqueue=%d wqueue=%d " + "saddr=%s sport=%d " + "daddr=%s dport=%d>", + sstate_name[self->msg.idiag_state], + self->msg.idiag_rqueue, + self->msg.idiag_wqueue, + bufsaddr, ntohs(self->msg.id.idiag_sport), + bufdaddr, ntohs(self->msg.id.idiag_dport)); + return 0; +} + +static char inet_socket__daddr_doc__[] = +"daddr() -- get internet socket destination address"; +static PyObject *inet_socket__daddr(struct inet_socket *self, + PyObject *args __unused) +{ + char buf[1024]; + inet_ntop(self->msg.idiag_family, &self->msg.id.idiag_dst, + buf, sizeof(buf)); + return PyString_FromString(buf); +} + +static char inet_socket__saddr_doc__[] = +"saddr() -- get internet socket source address"; +static PyObject *inet_socket__saddr(struct inet_socket *self, + PyObject *args __unused) +{ + char buf[1024]; + inet_ntop(self->msg.idiag_family, &self->msg.id.idiag_src, + buf, sizeof(buf)); + return PyString_FromString(buf); +} + +static char inet_socket__dport_doc__[] = +"sport() -- get internet socket destination port"; +static PyObject *inet_socket__dport(struct inet_socket *self, + PyObject *args __unused) +{ + return Py_BuildValue("i", ntohs(self->msg.id.idiag_dport)); +} + +static char inet_socket__sport_doc__[] = +"sport() -- get internet socket source port"; +static PyObject *inet_socket__sport(struct inet_socket *self, + PyObject *args __unused) +{ + return Py_BuildValue("i", ntohs(self->msg.id.idiag_sport)); +} + +static char inet_socket__receive_queue_doc__[] = +"receive_queue() -- get internet socket receive queue length"; +static PyObject *inet_socket__receive_queue(struct inet_socket *self, + PyObject *args __unused) +{ + return Py_BuildValue("i", self->msg.idiag_rqueue); +} + +static char inet_socket__write_queue_doc__[] = +"write_queue() -- get internet socket write queue length"; +static PyObject *inet_socket__write_queue(struct inet_socket *self, + PyObject *args __unused) +{ + return Py_BuildValue("i", self->msg.idiag_wqueue); +} + +static char inet_socket__state_doc__[] = +"sport() -- get internet socket state"; +static PyObject *inet_socket__state(struct inet_socket *self, + PyObject *args __unused) +{ + return PyString_FromString(sstate_name[self->msg.idiag_state]); +} + +static struct PyMethodDef inet_socket__methods[] = { + { + .ml_name = "daddr", + .ml_meth = (PyCFunction)inet_socket__daddr, + .ml_doc = inet_socket__daddr_doc__, + }, + { + .ml_name = "saddr", + .ml_meth = (PyCFunction)inet_socket__saddr, + .ml_doc = inet_socket__saddr_doc__, + }, + { + .ml_name = "dport", + .ml_meth = (PyCFunction)inet_socket__dport, + .ml_doc = inet_socket__dport_doc__, + }, + { + .ml_name = "sport", + .ml_meth = (PyCFunction)inet_socket__sport, + .ml_doc = inet_socket__sport_doc__, + }, + { + .ml_name = "receive_queue", + .ml_meth = (PyCFunction)inet_socket__receive_queue, + .ml_doc = inet_socket__receive_queue_doc__, + }, + { + .ml_name = "write_queue", + .ml_meth = (PyCFunction)inet_socket__write_queue, + .ml_doc = inet_socket__write_queue_doc__, + }, + { + .ml_name = "state", + .ml_meth = (PyCFunction)inet_socket__state, + .ml_doc = inet_socket__state_doc__, + }, + { + .ml_name = NULL, + } +}; + +static PyObject *inet_socket__getattr(struct inet_socket *self, char *name) +{ + /* module name */ + if (!strcmp(name, "__module__")) + return PyString_FromString("_inet_socket"); + + /* class name */ + if (!strcmp(name, "__class__")) + return PyString_FromString("inet_socket"); + + /* seeks name in methods (fallback) */ + return Py_FindMethod(inet_socket__methods, (PyObject *)self, name); +} + +static PyTypeObject inet_socket__type = { + PyObject_HEAD_INIT(NULL) + .tp_name = "inet_socket", + .tp_basicsize = sizeof(struct inet_socket), + .tp_dealloc = (destructor)inet_socket__dealloc, + .tp_print = (printfunc)inet_socket__print, + .tp_getattr = (getattrfunc)inet_socket__getattr, +}; + +/* constructor */ +static PyObject *inet_socket__new(struct inet_diag_msg *r) +{ + struct inet_socket *self; + + self = PyObject_NEW(struct inet_socket, &inet_socket__type); + if (self == NULL) + return NULL; + + self->msg = *r; + + return (PyObject *)self; +} + +struct inet_diag { + PyObject_HEAD + int socket; /* NETLINK socket */ + char buf[8192]; + struct nlmsghdr *h; + int len; +}; + +/* destructor */ +static void inet_diag__dealloc(struct inet_diag *self) +{ + close(self->socket); + PyObject_Del(self); +} + +/* prints query object in human readable format */ +static int inet_diag__print(struct inet_diag *self __unused, + FILE *fp, int flags __unused) +{ + if (self->socket >= 0) + fprintf(fp, "<Opened inet_diag socket>"); + else + fprintf(fp, "<Closed large object>"); + + return 0; +} + +static char inet_diag__get_doc__[] = +"read() -- read from inet_diag_sock. "; +static PyObject *inet_diag__get(struct inet_diag *self, PyObject *args __unused) +{ +try_again_nlmsg_ok: + if (!NLMSG_OK(self->h, self->len)) { + struct sockaddr_nl nladdr; +try_again_recvmsg: + { + struct iovec iov[1] = { + [0] = { + .iov_base = self->buf, + .iov_len = sizeof(self->buf), + }, + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = iov, + .msg_iovlen = 1, + }; + self->len = recvmsg(self->socket, &msg, 0); + + if (self->len < 0) { + if (errno == EINTR) + goto try_again_recvmsg; +out_eof: + close(self->socket); + PyErr_SetString(PyExc_OSError, strerror(errno)); + return NULL; + } + + if (self->len == 0) { /* EOF, how to signal properly? */ + close(self->socket); + PyErr_SetNone(PyExc_EOFError); + return NULL; + } + + self->h = (void *)self->buf; + } + } + + if (self->h->nlmsg_seq != 123456) { + self->h = NLMSG_NEXT(self->h, self->len); + goto try_again_nlmsg_ok; + } + + if (self->h->nlmsg_type == NLMSG_DONE) + goto out_eof; + + if (self->h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = NLMSG_DATA(self->h); + if (self->h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { + PyErr_SetString(PyExc_OSError, "message truncated"); + close(self->socket); + } else { + errno = -err->error; + PyErr_SetString(PyExc_OSError, strerror(errno)); + + } + return NULL; + } + + struct inet_diag_msg *r = NLMSG_DATA(self->h); + self->h = NLMSG_NEXT(self->h, self->len); + + return inet_socket__new(r); +} + +static struct PyMethodDef inet_diag__methods[] = { + { + .ml_name = "get", + .ml_meth = (PyCFunction)inet_diag__get, + .ml_flags = METH_VARARGS, + .ml_doc = inet_diag__get_doc__, + }, + { + .ml_name = NULL, + } +}; + +static PyObject *inet_diag__getattr(struct inet_diag *self, char *name) +{ + /* module name */ + if (!strcmp(name, "__module__")) + return PyString_FromString("_inet_diag"); + + /* class name */ + if (!strcmp(name, "__class__")) + return PyString_FromString("inet_diag"); + + /* seeks name in methods (fallback) */ + return Py_FindMethod(inet_diag__methods, (PyObject *)self, name); +} + +static PyTypeObject inet_diag_type = { + PyObject_HEAD_INIT(NULL) + .tp_name = "inet_diag", + .tp_basicsize = sizeof(struct inet_diag), + .tp_dealloc = (destructor)inet_diag__dealloc, + .tp_print = (printfunc)inet_diag__print, + .tp_getattr = (getattrfunc)inet_diag__getattr, +}; + +/* constructor */ +static char inet_diag_create__doc__[] = +"create() -- creates a new inet_diag socket."; +static PyObject *inet_diag__create(PyObject *args __unused) +{ + struct inet_diag *self = PyObject_NEW(struct inet_diag, + &inet_diag_type); + if (self == NULL) + return NULL; + + self->socket = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG); + if (self->socket < 0) + goto out_err; + + struct sockaddr_nl nladdr = { + .nl_family = AF_NETLINK, + }; + struct { + struct nlmsghdr nlh; + struct inet_diag_req r; + } req = { + .nlh = { + .nlmsg_len = sizeof(req), + .nlmsg_type = TCPDIAG_GETSOCK, + .nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST, + .nlmsg_seq = 123456, + }, + .r = { + .idiag_family = AF_INET, + .idiag_states = default_states, + }, + }; + struct iovec iov[1] = { + [0] = { + .iov_base = &req, + .iov_len = sizeof(req), + }, + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = iov, + .msg_iovlen = 1, + }; + + if (sendmsg(self->socket, &msg, 0) < 0) + goto out_err; + + self->len = 0; + return (PyObject *)self; +out_err: + PyErr_SetString(PyExc_OSError, strerror(errno)); + Py_XDECREF(self); + return NULL; +} + +static struct PyMethodDef python_inet_diag__methods[] = { + { + .ml_name = "create", + .ml_meth = (PyCFunction)inet_diag__create, + .ml_flags = METH_VARARGS, + .ml_doc = inet_diag_create__doc__ + }, + { .ml_name = NULL, }, +}; + +PyMODINIT_FUNC initinet_diag(void) +{ + PyObject *m; + m = Py_InitModule("inet_diag", python_inet_diag__methods); + PyModule_AddIntConstant(m, "TCP_DB", TCP_DB); /* Select TCP sockets. */ + PyModule_AddIntConstant(m, "SS_ESTABLISHED", SS_ESTABLISHED); + PyModule_AddIntConstant(m, "SS_SYN_SENT", SS_SYN_SENT); + PyModule_AddIntConstant(m, "SS_SYN_RECV", SS_SYN_RECV); + PyModule_AddIntConstant(m, "SS_FIN_WAIT1", SS_FIN_WAIT1); + PyModule_AddIntConstant(m, "SS_FIN_WAIT2", SS_FIN_WAIT2); + PyModule_AddIntConstant(m, "SS_TIME_WAIT", SS_TIME_WAIT); + PyModule_AddIntConstant(m, "SS_CLOSE", SS_CLOSE); + PyModule_AddIntConstant(m, "SS_CLOSE_WAIT", SS_CLOSE_WAIT); + PyModule_AddIntConstant(m, "SS_LAST_ACK", SS_LAST_ACK); + PyModule_AddIntConstant(m, "SS_LISTEN", SS_LISTEN); + PyModule_AddIntConstant(m, "SS_CLOSING", SS_CLOSING); +} diff --git a/python-inet_diag/inet_diag_copy.h b/python-inet_diag/inet_diag_copy.h new file mode 100644 index 0000000..527e627 --- /dev/null +++ b/python-inet_diag/inet_diag_copy.h @@ -0,0 +1,123 @@ +#ifndef _INET_DIAG_H_ +#define _INET_DIAG_H_ 1 + +#include <linux/types.h> + +/* Just some random number */ +#define TCPDIAG_GETSOCK 18 +#define DCCPDIAG_GETSOCK 19 + +#define INET_DIAG_GETSOCK_MAX 24 + +/* Socket identity */ +struct inet_diag_sockid { + __be16 idiag_sport; + __be16 idiag_dport; + __be32 idiag_src[4]; + __be32 idiag_dst[4]; + __u32 idiag_if; + __u32 idiag_cookie[2]; +#define INET_DIAG_NOCOOKIE (~0U) +}; + +/* Request structure */ + +struct inet_diag_req { + __u8 idiag_family; /* Family of addresses. */ + __u8 idiag_src_len; + __u8 idiag_dst_len; + __u8 idiag_ext; /* Query extended information */ + + struct inet_diag_sockid id; + + __u32 idiag_states; /* States to dump */ + __u32 idiag_dbs; /* Tables to dump (NI) */ +}; + +enum { + INET_DIAG_REQ_NONE, + INET_DIAG_REQ_BYTECODE, +}; + +#define INET_DIAG_REQ_MAX INET_DIAG_REQ_BYTECODE + +/* Bytecode is sequence of 4 byte commands followed by variable arguments. + * All the commands identified by "code" are conditional jumps forward: + * to offset cc+"yes" or to offset cc+"no". "yes" is supposed to be + * length of the command and its arguments. + */ + +struct inet_diag_bc_op { + unsigned char code; + unsigned char yes; + unsigned short no; +}; + +enum { + INET_DIAG_BC_NOP, + INET_DIAG_BC_JMP, + INET_DIAG_BC_S_GE, + INET_DIAG_BC_S_LE, + INET_DIAG_BC_D_GE, + INET_DIAG_BC_D_LE, + INET_DIAG_BC_AUTO, + INET_DIAG_BC_S_COND, + INET_DIAG_BC_D_COND, +}; + +struct inet_diag_hostcond { + __u8 family; + __u8 prefix_len; + int port; + __be32 addr[0]; +}; + +/* Base info structure. It contains socket identity (addrs/ports/cookie) + * and, alas, the information shown by netstat. */ +struct inet_diag_msg { + __u8 idiag_family; + __u8 idiag_state; + __u8 idiag_timer; + __u8 idiag_retrans; + + struct inet_diag_sockid id; + + __u32 idiag_expires; + __u32 idiag_rqueue; + __u32 idiag_wqueue; + __u32 idiag_uid; + __u32 idiag_inode; +}; + +/* Extensions */ + +enum { + INET_DIAG_NONE, + INET_DIAG_MEMINFO, + INET_DIAG_INFO, + INET_DIAG_VEGASINFO, + INET_DIAG_CONG, +}; + +#define INET_DIAG_MAX INET_DIAG_CONG + + +/* INET_DIAG_MEM */ + +struct inet_diag_meminfo { + __u32 idiag_rmem; + __u32 idiag_wmem; + __u32 idiag_fmem; + __u32 idiag_tmem; +}; + +/* INET_DIAG_VEGASINFO */ + +struct tcpvegas_info { + __u32 tcpv_enabled; + __u32 tcpv_rttcnt; + __u32 tcpv_rtt; + __u32 tcpv_minrtt; +}; + +#endif /* _INET_DIAG_H_ */ diff --git a/rpm/SPECS/python-inet_diag.spec b/rpm/SPECS/python-inet_diag.spec new file mode 100644 index 0000000..6b6b078 --- /dev/null +++ b/rpm/SPECS/python-inet_diag.spec @@ -0,0 +1,45 @@ +%{!?pytho1_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} +%{!?python_ver: %define python_ver %(%{__python} -c "import sys ; print sys.version[:3]")} + +Summary: Ethernet settings python bindings +Name: python-inet_diag +Version: 0.1 +Release: 1%{?dist} +URL: http://git.kernel.org/?p=linux/kernel/git/acme/python-inet_diag.git +Source: http://userweb.kernel.org/~acme/python-inet_diag/%{name}-%{version}.tar.bz2 +License: GPLv2 +Group: System Environment/Libraries +BuildRequires: python-devel +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +%description +Python bindings for the inet_diag kernel interface, that allows querying AF_INET +socket state. + +%prep +%setup -q + +%build +%{__python} setup.py build + +%install +rm -rf %{buildroot} +%{__python} setup.py install --skip-build --root %{buildroot} +mkdir -p %{buildroot}%{_sbindir} +cp -p pss.py %{buildroot}%{_sbindir}/pss + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root) +%doc COPYING +%{_sbindir}/pss +%{python_sitearch}/inet_diag.so +%if "%{python_ver}" >= "2.5" +%{python_sitearch}/*.egg-info +%endif + +%changelog +* Mon Apr 27 2009 Arnaldo Carvalho de Melo <acme@redhat.com> - 0.1-1 +- Initial package diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..865fd87 --- /dev/null +++ b/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/python2 + +from distutils.core import setup, Extension + +inet_diag = Extension('inet_diag', + sources = ['python-inet_diag/inet_diag.c']) + +# don't reformat this line, Makefile parses it +setup(name='inet_diag', + version='0.1', + description='Python module to interface with inet_diag', + author='Arnaldo Carvalho de Melo', + author_email='acme@redhat.com', + url='http://fedoraproject.org/wiki/python-inet_diag', + ext_modules=[inet_diag]) |