*** empty log message ***
[nodemanager.git] / sioc.c
1 /*
2  * Extension to gather information about network interfaces
3  *
4  * Mark Huang <mlhuang@cs.princeton.edu>
5  * Copyright (C) 2006 The Trustees of Princeton University
6  *
7  * $Id$
8  */
9
10 #include <Python.h>
11
12 /* struct ifreq */
13 #include <net/if.h>
14
15 /* socket() */
16 #include <sys/types.h>
17 #include <sys/socket.h>
18
19 /* ioctl() */
20 #include <sys/ioctl.h>
21
22 /* inet_ntoa() */
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25
26 /* ARPHRD_ETHER */
27 #include <net/if_arp.h>
28
29 /* ETH_ALEN */
30 #include <net/ethernet.h>
31
32 static PyObject *
33 gifconf(PyObject *self, PyObject *args)
34 {
35         struct ifconf ifc;
36         int len;
37         int s;
38         PyObject *addrs;
39         void *buf;
40         struct ifreq *ifr;
41         struct sockaddr_in *sin;
42
43         if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
44                 return PyErr_SetFromErrno(PyExc_OSError);
45
46         len = sizeof(struct ifreq);
47         ifc.ifc_len = 0;
48         ifc.ifc_req = NULL;
49
50         do {
51                 len *= 2;
52                 buf = realloc(ifc.ifc_req, len);
53                 if (!buf)
54                         break;
55                 ifc.ifc_len = len;
56                 ifc.ifc_req = buf;
57                 if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
58                         break;
59         } while (ifc.ifc_len >= len);
60
61         close(s);
62
63         addrs = Py_BuildValue("{}");
64
65         for (ifr = ifc.ifc_req, len = ifc.ifc_len; len > 0; ifr++, len -= sizeof(struct ifreq)) {
66                 sin = (struct sockaddr_in *) &ifr->ifr_addr;
67                 PyDict_SetItem(addrs,
68                                Py_BuildValue("s", ifr->ifr_name),
69                                Py_BuildValue("s", inet_ntoa(sin->sin_addr)));
70         }
71
72         if (ifc.ifc_req)
73                 free(ifc.ifc_req);
74
75         return addrs;
76 }
77
78 static PyObject *
79 gifaddr(PyObject *self, PyObject *args)
80 {
81         const char *name;
82         struct ifreq ifr;
83         int s;
84         struct sockaddr_in *sin;
85
86         if (!PyArg_ParseTuple(args, "s", &name))
87                 return NULL;
88
89         memset(&ifr, 0, sizeof(ifr));
90         strncpy(ifr.ifr_name, name, IFNAMSIZ);
91
92         if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
93                 return PyErr_SetFromErrno(PyExc_OSError);
94
95         if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
96                 close(s);
97                 return PyErr_SetFromErrno(PyExc_OSError);
98         }
99
100         close(s);
101
102         sin = (struct sockaddr_in *) &ifr.ifr_addr;
103         return Py_BuildValue("s", inet_ntoa(sin->sin_addr));
104 }
105
106 static PyObject *
107 gifhwaddr(PyObject *self, PyObject *args)
108 {
109         const char *name;
110         struct ifreq ifr;
111         int s;
112         char mac[sizeof(ifr.ifr_hwaddr.sa_data) * 3], *c;
113         int len, i;
114
115         if (!PyArg_ParseTuple(args, "s", &name))
116                 return NULL;
117
118         memset(&ifr, 0, sizeof(ifr));
119         strncpy(ifr.ifr_name, name, IFNAMSIZ);
120
121         if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
122                 return PyErr_SetFromErrno(PyExc_OSError);
123
124         if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
125                 close(s);
126                 return PyErr_SetFromErrno(PyExc_OSError);
127         }
128
129         close(s);
130
131         switch (ifr.ifr_hwaddr.sa_family) {
132         case ARPHRD_ETHER:
133                 len = ETH_ALEN;
134                 break;
135         default:
136                 len = sizeof(ifr.ifr_hwaddr.sa_data);
137                 break;
138         }
139
140         for (i = 0, c = mac; i < len; i++) {
141                 if (i)
142                         c += sprintf(c, ":");
143                 c += sprintf(c, "%02X", (unsigned char)(ifr.ifr_hwaddr.sa_data[i] & 0xFF));
144         }
145
146         return Py_BuildValue("s", mac);
147 }
148
149 static PyMethodDef  methods[] = {
150         { "gifconf", gifconf, METH_VARARGS, "Get all interface addresses" },
151         { "gifaddr", gifaddr, METH_VARARGS, "Get interface address" },
152         { "gifhwaddr", gifhwaddr, METH_VARARGS, "Get interface hardware address" },
153         { NULL, NULL, 0, NULL }
154 };
155
156 PyMODINIT_FUNC
157 initsioc(void)
158 {
159         Py_InitModule("sioc", methods);
160 }