Free a buffer on an error path
[pytipc.git] / tipc_ll.c
blobfb623fe4a9165cbe867325942c4114cdae96ac40
2 /*
3 * Python bindings for TIPC
4 * Alberto Bertogli (albertito@gmail.com)
6 * This is the low-level module, used by the python one to construct
7 * friendlier objects.
8 */
10 #include <Python.h>
12 #include <sys/types.h> /* socket defines */
13 #include <sys/socket.h> /* socket functions */
14 #include <stdlib.h> /* malloc() */
15 #include <stdint.h> /* uint32_t and friends */
16 #include <arpa/inet.h> /* htonls() and friends */
17 #include <string.h> /* memcpy() */
19 #include <linux/tipc.h> /* TIPC stuff */
23 * Internal useful functions
26 static int fill_sockaddr(struct sockaddr_tipc *sa, PyObject *addr)
28 unsigned int atype, v1, v2, v3;
29 unsigned int scope = TIPC_CLUSTER_SCOPE;
31 if (!PyArg_ParseTuple(addr, "IIII|I;Invalid TIPC address format",
32 &atype, &v1, &v2, &v3, &scope))
33 return 0;
35 memset(sa, 0, sizeof(struct sockaddr_tipc));
37 sa->family = AF_TIPC;
38 sa->scope = scope;
39 sa->addrtype = atype;
41 if (atype == TIPC_ADDR_NAMESEQ) {
42 sa->addr.nameseq.type = v1;
43 sa->addr.nameseq.lower = v2;
44 sa->addr.nameseq.upper = v3;
45 } else if (atype == TIPC_ADDR_NAME) {
46 sa->addr.name.name.type = v1;
47 sa->addr.name.name.instance = v2;
48 } else if (atype == TIPC_ADDR_ID) {
49 sa->addr.id.node = v1;
50 sa->addr.id.ref = v2;
51 } else {
52 /* Shouldn't happen */
53 PyErr_SetString(PyExc_TypeError, "Invalid address type");
54 return 0;
57 return 1;
60 static PyObject *sa_to_tuple(const struct sockaddr_tipc *sa)
62 if (sa->addrtype == TIPC_ADDR_NAMESEQ) {
63 return Py_BuildValue("IIIII",
64 sa->addrtype,
65 sa->addr.nameseq.type,
66 sa->addr.nameseq.lower,
67 sa->addr.nameseq.upper,
68 sa->scope);
69 } else if (sa->addrtype == TIPC_ADDR_NAME) {
70 return Py_BuildValue("IIIII",
71 sa->addrtype,
72 sa->addr.name.name.type,
73 sa->addr.name.name.instance,
74 sa->addr.name.name.instance,
75 sa->scope);
76 } else if (sa->addrtype == TIPC_ADDR_ID) {
77 return Py_BuildValue("IIIII",
78 sa->addrtype,
79 sa->addr.id.node,
80 sa->addr.id.ref,
82 sa->scope);
83 } else {
84 /* Shouldn't happen */
85 PyErr_SetString(PyExc_TypeError, "Invalid address type");
86 return NULL;
92 * Exported functions
95 static PyObject *tipc_socket(PyObject *self, PyObject *args)
97 int fd, stype;
99 if (!PyArg_ParseTuple(args, "i:tipc_socket", &stype)) {
100 return NULL;
103 Py_BEGIN_ALLOW_THREADS
104 fd = socket(AF_TIPC, stype, 0);
105 Py_END_ALLOW_THREADS
106 if (fd < 0)
107 return PyErr_SetFromErrno(PyExc_IOError);
109 return PyLong_FromLong(fd);
113 static PyObject *tipc_bind(PyObject *self, PyObject *args)
115 int fd, rv;
116 struct sockaddr_tipc sa;
117 PyObject *addr;
119 if (!PyArg_ParseTuple(args, "iO:tipc_bind", &fd, &addr))
120 return NULL;
122 if (!fill_sockaddr(&sa, addr))
123 return NULL;
125 Py_BEGIN_ALLOW_THREADS
126 rv = bind(fd, (struct sockaddr *) &sa, sizeof(sa));
127 Py_END_ALLOW_THREADS
129 if (rv < 0)
130 return PyErr_SetFromErrno(PyExc_IOError);
132 return PyLong_FromLong(rv);
136 static PyObject *tipc_connect(PyObject *self, PyObject *args)
138 int fd, rv;
139 struct sockaddr_tipc sa;
140 PyObject *addr;
142 if (!PyArg_ParseTuple(args, "iO:tipc_connect", &fd, &addr))
143 return NULL;
145 if (!fill_sockaddr(&sa, addr))
146 return NULL;
148 Py_BEGIN_ALLOW_THREADS
149 rv = connect(fd, (struct sockaddr *) &sa, sizeof(sa));
150 Py_END_ALLOW_THREADS
152 if (rv < 0)
153 return PyErr_SetFromErrno(PyExc_IOError);
155 return PyLong_FromLong(rv);
159 static PyObject *tipc_accept(PyObject *self, PyObject *args)
161 int fd, newfd;
162 struct sockaddr_tipc sa;
163 socklen_t salen = sizeof(sa);
165 if (!PyArg_ParseTuple(args, "i:tipc_accept", &fd)) {
166 return NULL;
169 Py_BEGIN_ALLOW_THREADS
170 newfd = accept(fd, (struct sockaddr *) &sa, &salen);
171 Py_END_ALLOW_THREADS
173 if (newfd < 0)
174 return PyErr_SetFromErrno(PyExc_IOError);
175 return Py_BuildValue("iN", newfd, sa_to_tuple(&sa));
179 static PyObject *tipc_sendto(PyObject *self, PyObject *args)
181 int fd, rv;
182 char *buf;
183 ssize_t len = 0;
184 struct sockaddr_tipc sa;
185 PyObject *addr;
187 if (!PyArg_ParseTuple(args, "is#O:tipc_sendto", &fd, &buf, &len, &addr))
188 return NULL;
190 if (!fill_sockaddr(&sa, addr))
191 return NULL;
193 Py_BEGIN_ALLOW_THREADS
194 rv = sendto(fd, buf, len, 0, (struct sockaddr *) &sa, sizeof(sa));
195 Py_END_ALLOW_THREADS
197 if (rv < 0)
198 return PyErr_SetFromErrno(PyExc_IOError);
200 return PyLong_FromLong(rv);
203 static PyObject *tipc_recvfrom(PyObject *self, PyObject *args)
205 int fd;
206 char *buf;
207 size_t maxlen = 0;
208 struct sockaddr_tipc sa;
209 socklen_t salen = sizeof(sa);
210 int rv;
211 PyObject *str;
213 if (!PyArg_ParseTuple(args, "iI:tipc_recvfrom", &fd, &maxlen)) {
214 return NULL;
217 buf = malloc(maxlen);
218 if (buf == NULL)
219 return PyErr_NoMemory();
221 Py_BEGIN_ALLOW_THREADS
222 rv = recvfrom(fd, buf, maxlen, 0,
223 (struct sockaddr *) &sa, &salen);
224 Py_END_ALLOW_THREADS
226 if (rv < 0) {
227 free(buf);
228 return PyErr_SetFromErrno(PyExc_IOError);
231 str = PyString_FromStringAndSize(buf, rv);
232 free(buf);
234 return Py_BuildValue("NN", str, sa_to_tuple(&sa));
237 static PyObject *tipc_build_subscr(PyObject *self, PyObject *args)
239 int stype, lower, upper;
240 uint32_t timeout, filter;
241 struct tipc_subscr subs;
243 if (!PyArg_ParseTuple(args, "IIIII:tipc_build_subscr",
244 &stype, &lower, &upper, &timeout, &filter)) {
245 return NULL;
248 subs.seq.type = stype;
249 subs.seq.lower = lower;
250 subs.seq.upper = upper;
251 subs.timeout = timeout;
252 subs.filter = filter;
254 return PyString_FromStringAndSize((char *) &subs,
255 sizeof(subs));
258 static PyObject *tipc_parse_event(PyObject *self, PyObject *args)
260 unsigned char *buf;
261 ssize_t len = 0;
262 struct tipc_event *event;
264 if (!PyArg_ParseTuple(args, "s#:tipc_parse_event",
265 &buf, &len)) {
266 return NULL;
269 /* Return None if the buffer looks strange */
270 if (len < sizeof(event))
271 return Py_BuildValue("");
273 event = (struct tipc_event *) buf;
275 return Py_BuildValue("III(IIIII)",
276 event->event,
277 event->found_lower,
278 event->found_upper,
279 event->s.seq.type,
280 event->s.seq.lower,
281 event->s.seq.upper,
282 event->s.timeout,
283 event->s.filter);
289 static PyMethodDef pytipc_functions[] = {
290 { "socket", (PyCFunction) tipc_socket, METH_VARARGS, NULL },
291 { "bind", (PyCFunction) tipc_bind, METH_VARARGS, NULL },
292 { "connect", (PyCFunction) tipc_connect, METH_VARARGS, NULL },
293 { "accept", (PyCFunction) tipc_accept, METH_VARARGS, NULL },
294 { "sendto", (PyCFunction) tipc_sendto, METH_VARARGS, NULL },
295 { "recvfrom", (PyCFunction) tipc_recvfrom, METH_VARARGS, NULL },
296 { "build_subscr", (PyCFunction) tipc_build_subscr, METH_VARARGS, NULL },
297 { "parse_event", (PyCFunction) tipc_parse_event, METH_VARARGS, NULL },
298 { NULL }
301 PyMODINIT_FUNC inittipc_ll(void)
303 PyObject *m;
305 m = Py_InitModule("tipc_ll", pytipc_functions);
306 PyModule_AddIntConstant(m, "AF_TIPC", AF_TIPC);
308 /* for addresses */
309 PyModule_AddIntConstant(m, "TIPC_ADDR_NAMESEQ", TIPC_ADDR_NAMESEQ);
310 PyModule_AddIntConstant(m, "TIPC_ADDR_NAME", TIPC_ADDR_NAME);
311 PyModule_AddIntConstant(m, "TIPC_ADDR_ID", TIPC_ADDR_ID);
313 PyModule_AddIntConstant(m, "TIPC_ZONE_SCOPE", TIPC_ZONE_SCOPE);
314 PyModule_AddIntConstant(m, "TIPC_CLUSTER_SCOPE", TIPC_CLUSTER_SCOPE);
315 PyModule_AddIntConstant(m, "TIPC_NODE_SCOPE", TIPC_NODE_SCOPE);
318 /* for setsockopt() */
319 PyModule_AddIntConstant(m, "SOL_TIPC", SOL_TIPC);
320 PyModule_AddIntConstant(m, "TIPC_IMPORTANCE", TIPC_IMPORTANCE);
321 PyModule_AddIntConstant(m, "TIPC_SRC_DROPPABLE", TIPC_SRC_DROPPABLE);
322 PyModule_AddIntConstant(m, "TIPC_DEST_DROPPABLE",
323 TIPC_DEST_DROPPABLE);
324 PyModule_AddIntConstant(m, "TIPC_CONN_TIMEOUT", TIPC_CONN_TIMEOUT);
326 PyModule_AddIntConstant(m, "TIPC_LOW_IMPORTANCE",
327 TIPC_LOW_IMPORTANCE);
328 PyModule_AddIntConstant(m, "TIPC_MEDIUM_IMPORTANCE",
329 TIPC_MEDIUM_IMPORTANCE);
330 PyModule_AddIntConstant(m, "TIPC_HIGH_IMPORTANCE",
331 TIPC_HIGH_IMPORTANCE);
332 PyModule_AddIntConstant(m, "TIPC_CRITICAL_IMPORTANCE",
333 TIPC_CRITICAL_IMPORTANCE);
335 /* for subscriptions */
336 PyModule_AddIntConstant(m, "TIPC_SUB_PORTS", TIPC_SUB_PORTS);
337 PyModule_AddIntConstant(m, "TIPC_SUB_SERVICE", TIPC_SUB_SERVICE);
338 PyModule_AddIntConstant(m, "TIPC_SUB_CANCEL", TIPC_SUB_CANCEL);
339 PyModule_AddIntConstant(m, "TIPC_WAIT_FOREVER", TIPC_WAIT_FOREVER);
340 PyModule_AddIntConstant(m, "TIPC_PUBLISHED", TIPC_PUBLISHED);
341 PyModule_AddIntConstant(m, "TIPC_WITHDRAWN", TIPC_WITHDRAWN);
342 PyModule_AddIntConstant(m, "TIPC_SUBSCR_TIMEOUT", TIPC_SUBSCR_TIMEOUT);
343 PyModule_AddIntConstant(m, "TIPC_CFG_SRV", TIPC_CFG_SRV);
344 PyModule_AddIntConstant(m, "TIPC_TOP_SRV", TIPC_TOP_SRV);