CI opt-test: Drop Python2 & Bash in Fedora latest.
[ntpsec.git] / libntp / pymodule.c
blob844544bf4bba0f10ffff392f2631ded1e311d5bb
1 /*
2 * Copyright the NTPsec project contributors
3 * SPDX-License-Identifier: BSD-2-Clause
5 * Python binding for selected libntp library functions
6 */
8 /* This include has to come early or we get warnings from redefining
9 * _POSIX_C_SOURCE and _XOPEN_SOURCE on some systems.
11 #define PY_SSIZE_T_CLEAN
12 #include <Python.h>
14 #include "config.h"
16 #include "ntp_machine.h"
17 #include "ntpd.h"
18 #include "ntp_io.h"
19 #include "ntp_fp.h"
20 #include "ntp_stdlib.h"
21 #include "ntp_syslog.h"
22 #include "timespecops.h"
24 #include "ntp_config.h"
25 #include "ntp_assert.h"
27 #include "ntp_control.h"
29 #include "pymodule-mac.h"
31 #include "python_compatibility.h"
33 /* Don't include anything from OpenSSL */
35 const char *progname = "libntpc";
38 * Client utility functions
41 static PyObject *
42 ntpc_setprogname(PyObject *self, PyObject *args)
44 char *s;
45 UNUSED_ARG(self);
46 if (!PyArg_ParseTuple(args, "s", &s))
47 return NULL;
48 progname = strdup(s);
51 * This function is only called from clients. Therefore
52 * log to stderr rather than syslog, and suppress logfile
53 * impediments. If we ever want finer-grained control, that
54 * will be easily implemented with additional arguments.
56 syslogit = false; /* don't log messages to syslog */
57 termlogit = true; /* duplicate to stdout/err */
58 termlogit_pid = false;
59 msyslog_include_timestamp = false;
61 Py_RETURN_NONE;
64 static PyObject *
65 ntpc_statustoa(PyObject *self, PyObject *args)
67 int status1, status2;
68 char *gs;
70 UNUSED_ARG(self);
71 if (!PyArg_ParseTuple(args, "ii", &status1, &status2))
72 return NULL;
73 gs = statustoa(status1, status2);
74 return Py_BuildValue("s", gs);
77 static PyObject *
78 ntpc_prettydate(PyObject *self, PyObject *args)
80 char *s;
81 l_fp ts;
83 UNUSED_ARG(self);
84 if (!PyArg_ParseTuple(args, "s", &s))
85 return NULL;
86 if (hextolfp(s+2, &ts))
87 return Py_BuildValue("s", prettydate(ts));
88 else {
89 PyErr_SetString(PyExc_ValueError, "ill-formed hex date");
90 return NULL;
94 static PyObject *
95 ntpc_lfptofloat(PyObject *self, PyObject *args)
97 char *s;
98 l_fp ts;
99 struct timespec tt;
101 UNUSED_ARG(self);
102 if (!PyArg_ParseTuple(args, "s", &s))
103 return NULL;
104 if (!hextolfp(s+2, &ts)) {
105 PyErr_SetString(PyExc_ValueError, "ill-formed hex date");
106 return NULL;
108 tt = lfp_stamp_to_tspec(ts, time(NULL));
109 return Py_BuildValue("d", tt.tv_sec + tt.tv_nsec * S_PER_NS);
112 static PyObject *
113 ntpc_adj_systime(PyObject *self, PyObject *args)
115 double adjustment;
117 UNUSED_ARG(self);
118 if (!PyArg_ParseTuple(args, "d", &adjustment))
119 return NULL;
120 return Py_BuildValue("d", adj_systime(adjustment, adjtime) ? 1 : 0);
123 static PyObject *
124 ntpc_step_systime(PyObject *self, PyObject *args)
126 double adjustment;
127 doubletime_t full_adjustment;
129 UNUSED_ARG(self);
131 * What we really want is for Python to parse a long double.
132 * As this is, it's a potential source of problems in the Python
133 * utilities if and when the time difference between the Unix epoch
134 * and now exceeds the range of a double.
136 if (!PyArg_ParseTuple(args, "d", &adjustment))
137 return NULL;
138 full_adjustment = adjustment;
139 return Py_BuildValue("d", step_systime(full_adjustment));
142 /* --------------------------------------------------------------- */
143 /* Hook for CMAC/HMAC
144 * Not really part of libntp, but this is a handy place to put it.
146 * The worker parts have been moved to another module because of
147 * name clash between python and OpenSSL. Both use freefunc.
149 * All Python stuff here. All OpenSSL stuff in pymodule-mac.c
154 /* xx = ntp.ntpc.checkname(name)
155 * returns None if algorithm name is invalid. */
157 static PyObject *
158 ntpc_checkname(PyObject *self, PyObject *args)
160 const char *name;
161 UNUSED_ARG(self);
162 int length;
164 if (!PyArg_ParseTuple(args, "s", &name))
165 Py_RETURN_NONE;
167 length = do_checkname(name);
169 if (length != 0) return Py_BuildValue("i", 1);
171 Py_RETURN_NONE;
175 /* mac = ntp.ntpc.mac(data, key, name) */
177 static PyObject *
178 ntpc_mac(PyObject *self, PyObject *args)
180 UNUSED_ARG(self);
181 uint8_t *data;
182 Py_ssize_t datalen;
183 uint8_t *key;
184 Py_ssize_t keylen;
185 char *name;
186 uint8_t mac[MAX_MAC_LENGTH];
187 size_t maclen;
190 #if PY_MAJOR_VERSION >= 3
191 if (!PyArg_ParseTuple(args, "y#y#s",
192 &data, &datalen, &key, &keylen, &name))
193 #else
194 if (!PyArg_ParseTuple(args, "s#s#s",
195 &data, &datalen, &key, &keylen, &name))
196 #endif
197 Py_RETURN_NONE;
199 do_mac(name,
200 data, datalen,
201 key, keylen,
202 mac, &maclen);
204 if (maclen == 0)
205 Py_RETURN_NONE;
207 #if PY_MAJOR_VERSION >= 3
208 return Py_BuildValue("y#", &mac, maclen);
209 #else
210 return Py_BuildValue("s#", &mac, maclen);
211 #endif
214 /* List of functions defined in the module */
216 static PyMethodDef ntpc_methods[] = {
217 {"setprogname", ntpc_setprogname, METH_VARARGS,
218 PyDoc_STR("Set program name for logging purposes.")},
219 {"statustoa", ntpc_statustoa, METH_VARARGS,
220 PyDoc_STR("Status string display from peer status word.")},
221 {"prettydate", ntpc_prettydate, METH_VARARGS,
222 PyDoc_STR("Convert a time stamp to something readable.")},
223 {"lfptofloat", ntpc_lfptofloat, METH_VARARGS,
224 PyDoc_STR("NTP l_fp to Python-style float time.")},
225 {"adj_systime", ntpc_adj_systime, METH_VARARGS,
226 PyDoc_STR("Adjust system time by slewing.")},
227 {"step_systime", ntpc_step_systime, METH_VARARGS,
228 PyDoc_STR("Adjust system time by stepping.")},
229 {"checkname", ntpc_checkname, METH_VARARGS,
230 PyDoc_STR("Check if name is a valid algorithm name")},
231 {"mac", ntpc_mac, METH_VARARGS,
232 PyDoc_STR("Compute HMAC or CMAC from data, key, and algorithm name")},
233 {NULL, NULL, 0, NULL} /* sentinel */
236 PyDoc_STRVAR(module_doc,
237 "Python wrapper for selected libntp C library routines.\n\
240 /* banishes pointless compiler warnings on various Python versions */
241 extern PyMODINIT_FUNC initntpc(void);
242 extern PyMODINIT_FUNC PyInit_ntpc(void);
244 // cppcheck-suppress unusedFunction
245 NTPSEC_PY_MODULE_INIT(ntpc)
247 PyObject *m;
249 /* Create the module and add the functions */
250 NTPSEC_PY_MODULE_DEF(m, "ntpc", module_doc, ntpc_methods)
252 /* for statustoa() */
253 PyModule_AddIntConstant(m, "TYPE_SYS", TYPE_SYS);
254 PyModule_AddIntConstant(m, "TYPE_PEER", TYPE_PEER);
255 PyModule_AddIntConstant(m, "TYPE_CLOCK", TYPE_CLOCK);
257 if (m == NULL)
258 return NTPSEC_PY_MODULE_ERROR_VAL;
260 return NTPSEC_PY_MODULE_SUCCESS_VAL(m);