2 * Copyright the NTPsec project contributors
3 * SPDX-License-Identifier: BSD-2-Clause
5 * Python binding for selected libntp library functions
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
16 #include "ntp_machine.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
42 ntpc_setprogname(PyObject
*self
, PyObject
*args
)
46 if (!PyArg_ParseTuple(args
, "s", &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;
65 ntpc_statustoa(PyObject
*self
, PyObject
*args
)
71 if (!PyArg_ParseTuple(args
, "ii", &status1
, &status2
))
73 gs
= statustoa(status1
, status2
);
74 return Py_BuildValue("s", gs
);
78 ntpc_prettydate(PyObject
*self
, PyObject
*args
)
84 if (!PyArg_ParseTuple(args
, "s", &s
))
86 if (hextolfp(s
+2, &ts
))
87 return Py_BuildValue("s", prettydate(ts
));
89 PyErr_SetString(PyExc_ValueError
, "ill-formed hex date");
95 ntpc_lfptofloat(PyObject
*self
, PyObject
*args
)
102 if (!PyArg_ParseTuple(args
, "s", &s
))
104 if (!hextolfp(s
+2, &ts
)) {
105 PyErr_SetString(PyExc_ValueError
, "ill-formed hex date");
108 tt
= lfp_stamp_to_tspec(ts
, time(NULL
));
109 return Py_BuildValue("d", tt
.tv_sec
+ tt
.tv_nsec
* S_PER_NS
);
113 ntpc_adj_systime(PyObject
*self
, PyObject
*args
)
118 if (!PyArg_ParseTuple(args
, "d", &adjustment
))
120 return Py_BuildValue("d", adj_systime(adjustment
, adjtime
) ? 1 : 0);
124 ntpc_step_systime(PyObject
*self
, PyObject
*args
)
127 doubletime_t full_adjustment
;
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
))
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. */
158 ntpc_checkname(PyObject
*self
, PyObject
*args
)
164 if (!PyArg_ParseTuple(args
, "s", &name
))
167 length
= do_checkname(name
);
169 if (length
!= 0) return Py_BuildValue("i", 1);
175 /* mac = ntp.ntpc.mac(data, key, name) */
178 ntpc_mac(PyObject
*self
, PyObject
*args
)
186 uint8_t mac
[MAX_MAC_LENGTH
];
190 #if PY_MAJOR_VERSION >= 3
191 if (!PyArg_ParseTuple(args
, "y#y#s",
192 &data
, &datalen
, &key
, &keylen
, &name
))
194 if (!PyArg_ParseTuple(args
, "s#s#s",
195 &data
, &datalen
, &key
, &keylen
, &name
))
207 #if PY_MAJOR_VERSION >= 3
208 return Py_BuildValue("y#", &mac
, maclen
);
210 return Py_BuildValue("s#", &mac
, maclen
);
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
)
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
);
258 return NTPSEC_PY_MODULE_ERROR_VAL
;
260 return NTPSEC_PY_MODULE_SUCCESS_VAL(m
);