- /*
- * Yes, so we now know how many types to fetch.
- *
- * The buffer needs to have one ULONG for the
- * count and num_ts_modes ULONGs for the
- * num_ts_modes time stamp types.
- */
- modes = (ULONG *)malloc((1 + num_ts_modes) * sizeof(ULONG));
- if (modes == NULL) {
- /* Out of memory. */
- /* XXX SET ebuf */
- pcap_close(p);
- return (NULL);
- }
- modes[0] = 1 + num_ts_modes;
- if (!PacketGetTimestampModes(adapter, modes)) {
- pcap_fmt_errmsg_for_win32_err(ebuf,
- PCAP_ERRBUF_SIZE, GetLastError(),
- "Error calling PacketGetTimestampModes");
- free(modes);
- pcap_close(p);
- return (NULL);
- }
- if (modes[0] != num_ts_modes) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "First PacketGetTimestampModes() call gives %lu modes, second call gives %lu modes",
- num_ts_modes, modes[0]);
- free(modes);
- pcap_close(p);
- return (NULL);
- }
- if (num_ts_modes != 0) {
- u_int num_ts_types;
+ /* If the driver reports no modes supported *and*
+ * ERROR_MORE_DATA, something is seriously wrong.
+ * We *could* ignore the error and continue without supporting
+ * settable timestamp modes, but that would hide a bug.
+ */
+ if (num_ts_modes == 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "PacketGetTimestampModes() reports 0 modes supported.");
+ status = -1;
+ break;
+ }
+
+ /*
+ * Yes, so we now know how many types to fetch.
+ *
+ * The buffer needs to have one ULONG for the
+ * count and num_ts_modes ULONGs for the
+ * num_ts_modes time stamp types.
+ */
+ modes = (ULONG *)malloc((1 + num_ts_modes) * sizeof(ULONG));
+ if (modes == NULL) {
+ /* Out of memory. */
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "malloc");
+ status = -1;
+ break;
+ }
+ modes[0] = 1 + num_ts_modes;
+ if (!PacketGetTimestampModes(adapter, modes)) {
+ pcap_fmt_errmsg_for_win32_err(ebuf,
+ PCAP_ERRBUF_SIZE, GetLastError(),
+ "Error calling PacketGetTimestampModes");
+ status = -1;
+ break;
+ }
+ if (modes[0] != num_ts_modes) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "First PacketGetTimestampModes() call gives %lu modes, second call gives %lu modes",
+ num_ts_modes, modes[0]);
+ status = -1;
+ break;
+ }
+
+ /*
+ * Allocate a buffer big enough for
+ * PCAP_TSTAMP_HOST (default) plus
+ * the explicitly specified modes.
+ */
+ p->tstamp_type_list = malloc((1 + num_ts_modes) * sizeof(u_int));
+ if (p->tstamp_type_list == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, "malloc");
+ status = -1;
+ break;
+ }
+ u_int num_ts_types = 0;
+ p->tstamp_type_list[num_ts_types] =
+ PCAP_TSTAMP_HOST;
+ num_ts_types++;
+ for (ULONG i = 0; i < num_ts_modes; i++) {
+ switch (modes[i + 1]) {
+
+ case TIMESTAMPMODE_SINGLE_SYNCHRONIZATION:
+ /*
+ * Better than low-res,
+ * but *not* synchronized
+ * with the OS clock.
+ */
+ p->tstamp_type_list[num_ts_types] =
+ PCAP_TSTAMP_HOST_HIPREC_UNSYNCED;
+ num_ts_types++;
+ break;