The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 |
| 3 | * The Regents of the University of California. All rights reserved. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that: (1) source code distributions |
| 7 | * retain the above copyright notice and this paragraph in its entirety, (2) |
| 8 | * distributions including binary code include the above copyright notice and |
| 9 | * this paragraph in its entirety in the documentation or other materials |
| 10 | * provided with the distribution, and (3) all advertising materials mentioning |
| 11 | * features or use of this software display the following acknowledgement: |
| 12 | * ``This product includes software developed by the University of California, |
| 13 | * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
| 14 | * the University nor the names of its contributors may be used to endorse |
| 15 | * or promote products derived from this software without specific prior |
| 16 | * written permission. |
| 17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
| 18 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
| 19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| 20 | */ |
| 21 | |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 22 | /* |
| 23 | * txtproto_print() derived from original code by Hannes Gredler |
Elliott Hughes | cec480a | 2017-12-19 16:54:57 -0800 | [diff] [blame] | 24 | * (hannes@gredler.at): |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 25 | * |
| 26 | * Redistribution and use in source and binary forms, with or without |
| 27 | * modification, are permitted provided that: (1) source code |
| 28 | * distributions retain the above copyright notice and this paragraph |
| 29 | * in its entirety, and (2) distributions including binary code include |
| 30 | * the above copyright notice and this paragraph in its entirety in |
| 31 | * the documentation or other materials provided with the distribution. |
| 32 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND |
| 33 | * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT |
| 34 | * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 35 | * FOR A PARTICULAR PURPOSE. |
| 36 | */ |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 37 | |
| 38 | #ifdef HAVE_CONFIG_H |
| 39 | #include "config.h" |
| 40 | #endif |
| 41 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 42 | #include <netdissect-stdinc.h> |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 43 | |
| 44 | #include <sys/stat.h> |
| 45 | |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 46 | #ifdef HAVE_FCNTL_H |
| 47 | #include <fcntl.h> |
| 48 | #endif |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 49 | #include <ctype.h> |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 50 | #include <stdio.h> |
| 51 | #include <stdarg.h> |
| 52 | #include <stdlib.h> |
| 53 | #include <string.h> |
| 54 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 55 | #include "netdissect.h" |
| 56 | #include "ascii_strcasecmp.h" |
| 57 | #include "timeval-operations.h" |
| 58 | |
| 59 | int32_t thiszone; /* seconds offset from gmt to local time */ |
| 60 | /* invalid string to print '(invalid)' for malformed or corrupted packets */ |
| 61 | const char istr[] = " (invalid)"; |
| 62 | |
| 63 | /* |
| 64 | * timestamp display buffer size, the biggest size of both formats is needed |
| 65 | * sizeof("0000000000.000000000") > sizeof("00:00:00.000000000") |
| 66 | */ |
| 67 | #define TS_BUF_SIZE sizeof("0000000000.000000000") |
| 68 | |
| 69 | #define TOKBUFSIZE 128 |
| 70 | |
| 71 | /* |
| 72 | * Print out a character, filtering out the non-printable ones |
| 73 | */ |
| 74 | void |
| 75 | fn_print_char(netdissect_options *ndo, u_char c) |
| 76 | { |
| 77 | if (!ND_ISASCII(c)) { |
| 78 | c = ND_TOASCII(c); |
| 79 | ND_PRINT((ndo, "M-")); |
| 80 | } |
| 81 | if (!ND_ISPRINT(c)) { |
| 82 | c ^= 0x40; /* DEL to ?, others to alpha */ |
| 83 | ND_PRINT((ndo, "^")); |
| 84 | } |
| 85 | ND_PRINT((ndo, "%c", c)); |
| 86 | } |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 87 | |
| 88 | /* |
| 89 | * Print out a null-terminated filename (or other ascii string). |
| 90 | * If ep is NULL, assume no truncation check is needed. |
| 91 | * Return true if truncated. |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 92 | * Stop at ep (if given) or before the null char, whichever is first. |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 93 | */ |
| 94 | int |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 95 | fn_print(netdissect_options *ndo, |
| 96 | register const u_char *s, register const u_char *ep) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 97 | { |
| 98 | register int ret; |
| 99 | register u_char c; |
| 100 | |
| 101 | ret = 1; /* assume truncated */ |
| 102 | while (ep == NULL || s < ep) { |
| 103 | c = *s++; |
| 104 | if (c == '\0') { |
| 105 | ret = 0; |
| 106 | break; |
| 107 | } |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 108 | if (!ND_ISASCII(c)) { |
| 109 | c = ND_TOASCII(c); |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 110 | ND_PRINT((ndo, "M-")); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 111 | } |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 112 | if (!ND_ISPRINT(c)) { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 113 | c ^= 0x40; /* DEL to ?, others to alpha */ |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 114 | ND_PRINT((ndo, "^")); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 115 | } |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 116 | ND_PRINT((ndo, "%c", c)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 117 | } |
| 118 | return(ret); |
| 119 | } |
| 120 | |
| 121 | /* |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 122 | * Print out a null-terminated filename (or other ascii string) from |
| 123 | * a fixed-length buffer. |
| 124 | * If ep is NULL, assume no truncation check is needed. |
| 125 | * Return the number of bytes of string processed, including the |
| 126 | * terminating null, if not truncated. Return 0 if truncated. |
| 127 | */ |
| 128 | u_int |
| 129 | fn_printztn(netdissect_options *ndo, |
| 130 | register const u_char *s, register u_int n, register const u_char *ep) |
| 131 | { |
| 132 | register u_int bytes; |
| 133 | register u_char c; |
| 134 | |
| 135 | bytes = 0; |
| 136 | for (;;) { |
| 137 | if (n == 0 || (ep != NULL && s >= ep)) { |
| 138 | /* |
| 139 | * Truncated. This includes "no null before we |
| 140 | * got to the end of the fixed-length buffer". |
| 141 | * |
| 142 | * XXX - BOOTP says "null-terminated", which |
| 143 | * means the maximum length of the string, in |
| 144 | * bytes, is 1 less than the size of the buffer, |
| 145 | * as there must always be a terminating null. |
| 146 | */ |
| 147 | bytes = 0; |
| 148 | break; |
| 149 | } |
| 150 | |
| 151 | c = *s++; |
| 152 | bytes++; |
| 153 | n--; |
| 154 | if (c == '\0') { |
| 155 | /* End of string */ |
| 156 | break; |
| 157 | } |
| 158 | if (!ND_ISASCII(c)) { |
| 159 | c = ND_TOASCII(c); |
| 160 | ND_PRINT((ndo, "M-")); |
| 161 | } |
| 162 | if (!ND_ISPRINT(c)) { |
| 163 | c ^= 0x40; /* DEL to ?, others to alpha */ |
| 164 | ND_PRINT((ndo, "^")); |
| 165 | } |
| 166 | ND_PRINT((ndo, "%c", c)); |
| 167 | } |
| 168 | return(bytes); |
| 169 | } |
| 170 | |
| 171 | /* |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 172 | * Print out a counted filename (or other ascii string). |
| 173 | * If ep is NULL, assume no truncation check is needed. |
| 174 | * Return true if truncated. |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 175 | * Stop at ep (if given) or after n bytes, whichever is first. |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 176 | */ |
| 177 | int |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 178 | fn_printn(netdissect_options *ndo, |
| 179 | register const u_char *s, register u_int n, register const u_char *ep) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 180 | { |
| 181 | register u_char c; |
| 182 | |
| 183 | while (n > 0 && (ep == NULL || s < ep)) { |
| 184 | n--; |
| 185 | c = *s++; |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 186 | if (!ND_ISASCII(c)) { |
| 187 | c = ND_TOASCII(c); |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 188 | ND_PRINT((ndo, "M-")); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 189 | } |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 190 | if (!ND_ISPRINT(c)) { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 191 | c ^= 0x40; /* DEL to ?, others to alpha */ |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 192 | ND_PRINT((ndo, "^")); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 193 | } |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 194 | ND_PRINT((ndo, "%c", c)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 195 | } |
| 196 | return (n == 0) ? 0 : 1; |
| 197 | } |
| 198 | |
| 199 | /* |
| 200 | * Print out a null-padded filename (or other ascii string). |
| 201 | * If ep is NULL, assume no truncation check is needed. |
| 202 | * Return true if truncated. |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 203 | * Stop at ep (if given) or after n bytes or before the null char, |
| 204 | * whichever is first. |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 205 | */ |
| 206 | int |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 207 | fn_printzp(netdissect_options *ndo, |
| 208 | register const u_char *s, register u_int n, |
| 209 | register const u_char *ep) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 210 | { |
| 211 | register int ret; |
| 212 | register u_char c; |
| 213 | |
| 214 | ret = 1; /* assume truncated */ |
| 215 | while (n > 0 && (ep == NULL || s < ep)) { |
| 216 | n--; |
| 217 | c = *s++; |
| 218 | if (c == '\0') { |
| 219 | ret = 0; |
| 220 | break; |
| 221 | } |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 222 | if (!ND_ISASCII(c)) { |
| 223 | c = ND_TOASCII(c); |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 224 | ND_PRINT((ndo, "M-")); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 225 | } |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 226 | if (!ND_ISPRINT(c)) { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 227 | c ^= 0x40; /* DEL to ?, others to alpha */ |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 228 | ND_PRINT((ndo, "^")); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 229 | } |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 230 | ND_PRINT((ndo, "%c", c)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 231 | } |
| 232 | return (n == 0) ? 0 : ret; |
| 233 | } |
| 234 | |
| 235 | /* |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 236 | * Format the timestamp |
| 237 | */ |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 238 | static char * |
| 239 | ts_format(netdissect_options *ndo |
| 240 | #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION |
| 241 | _U_ |
| 242 | #endif |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 243 | , int sec, int usec, char *buf) |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 244 | { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 245 | const char *format; |
| 246 | |
| 247 | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION |
| 248 | switch (ndo->ndo_tstamp_precision) { |
| 249 | |
| 250 | case PCAP_TSTAMP_PRECISION_MICRO: |
| 251 | format = "%02d:%02d:%02d.%06u"; |
| 252 | break; |
| 253 | |
| 254 | case PCAP_TSTAMP_PRECISION_NANO: |
| 255 | format = "%02d:%02d:%02d.%09u"; |
| 256 | break; |
| 257 | |
| 258 | default: |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 259 | format = "%02d:%02d:%02d.{unknown}"; |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 260 | break; |
| 261 | } |
| 262 | #else |
| 263 | format = "%02d:%02d:%02d.%06u"; |
| 264 | #endif |
| 265 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 266 | snprintf(buf, TS_BUF_SIZE, format, |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 267 | sec / 3600, (sec % 3600) / 60, sec % 60, usec); |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 268 | |
| 269 | return buf; |
| 270 | } |
| 271 | |
| 272 | /* |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 273 | * Format the timestamp - Unix timeval style |
| 274 | */ |
| 275 | static char * |
| 276 | ts_unix_format(netdissect_options *ndo |
| 277 | #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION |
| 278 | _U_ |
| 279 | #endif |
| 280 | , int sec, int usec, char *buf) |
| 281 | { |
| 282 | const char *format; |
| 283 | |
| 284 | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION |
| 285 | switch (ndo->ndo_tstamp_precision) { |
| 286 | |
| 287 | case PCAP_TSTAMP_PRECISION_MICRO: |
| 288 | format = "%u.%06u"; |
| 289 | break; |
| 290 | |
| 291 | case PCAP_TSTAMP_PRECISION_NANO: |
| 292 | format = "%u.%09u"; |
| 293 | break; |
| 294 | |
| 295 | default: |
| 296 | format = "%u.{unknown}"; |
| 297 | break; |
| 298 | } |
| 299 | #else |
| 300 | format = "%u.%06u"; |
| 301 | #endif |
| 302 | |
| 303 | snprintf(buf, TS_BUF_SIZE, format, |
| 304 | (unsigned)sec, (unsigned)usec); |
| 305 | |
| 306 | return buf; |
| 307 | } |
| 308 | |
| 309 | /* |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 310 | * Print the timestamp |
| 311 | */ |
| 312 | void |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 313 | ts_print(netdissect_options *ndo, |
| 314 | register const struct timeval *tvp) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 315 | { |
| 316 | register int s; |
| 317 | struct tm *tm; |
| 318 | time_t Time; |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 319 | char buf[TS_BUF_SIZE]; |
| 320 | static struct timeval tv_ref; |
| 321 | struct timeval tv_result; |
| 322 | int negative_offset; |
| 323 | int nano_prec; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 324 | |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 325 | switch (ndo->ndo_tflag) { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 326 | |
| 327 | case 0: /* Default */ |
| 328 | s = (tvp->tv_sec + thiszone) % 86400; |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 329 | ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec, buf))); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 330 | break; |
| 331 | |
| 332 | case 1: /* No time stamp */ |
| 333 | break; |
| 334 | |
| 335 | case 2: /* Unix timeval style */ |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 336 | ND_PRINT((ndo, "%s ", ts_unix_format(ndo, |
| 337 | tvp->tv_sec, tvp->tv_usec, buf))); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 338 | break; |
| 339 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 340 | case 3: /* Microseconds/nanoseconds since previous packet */ |
| 341 | case 5: /* Microseconds/nanoseconds since first packet */ |
| 342 | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION |
| 343 | switch (ndo->ndo_tstamp_precision) { |
| 344 | case PCAP_TSTAMP_PRECISION_MICRO: |
| 345 | nano_prec = 0; |
| 346 | break; |
| 347 | case PCAP_TSTAMP_PRECISION_NANO: |
| 348 | nano_prec = 1; |
| 349 | break; |
| 350 | default: |
| 351 | nano_prec = 0; |
| 352 | break; |
| 353 | } |
| 354 | #else |
| 355 | nano_prec = 0; |
| 356 | #endif |
| 357 | if (!(netdissect_timevalisset(&tv_ref))) |
| 358 | tv_ref = *tvp; /* set timestamp for first packet */ |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 359 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 360 | negative_offset = netdissect_timevalcmp(tvp, &tv_ref, <); |
| 361 | if (negative_offset) |
| 362 | netdissect_timevalsub(&tv_ref, tvp, &tv_result, nano_prec); |
| 363 | else |
| 364 | netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec); |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 365 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 366 | ND_PRINT((ndo, (negative_offset ? "-" : " "))); |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 367 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 368 | ND_PRINT((ndo, "%s ", ts_format(ndo, |
| 369 | tv_result.tv_sec, tv_result.tv_usec, buf))); |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 370 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 371 | if (ndo->ndo_tflag == 3) |
| 372 | tv_ref = *tvp; /* set timestamp for previous packet */ |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 373 | break; |
| 374 | |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 375 | case 4: /* Default + Date */ |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 376 | s = (tvp->tv_sec + thiszone) % 86400; |
| 377 | Time = (tvp->tv_sec + thiszone) - s; |
| 378 | tm = gmtime (&Time); |
| 379 | if (!tm) |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 380 | ND_PRINT((ndo, "Date fail ")); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 381 | else |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 382 | ND_PRINT((ndo, "%04d-%02d-%02d %s ", |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 383 | tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 384 | ts_format(ndo, s, tvp->tv_usec, buf))); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 385 | break; |
| 386 | } |
| 387 | } |
| 388 | |
| 389 | /* |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 390 | * Print an unsigned relative number of seconds (e.g. hold time, prune timer) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 391 | * in the form 5m1s. This does no truncation, so 32230861 seconds |
| 392 | * is represented as 1y1w1d1h1m1s. |
| 393 | */ |
| 394 | void |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 395 | unsigned_relts_print(netdissect_options *ndo, |
| 396 | uint32_t secs) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 397 | { |
| 398 | static const char *lengths[] = {"y", "w", "d", "h", "m", "s"}; |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 399 | static const u_int seconds[] = {31536000, 604800, 86400, 3600, 60, 1}; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 400 | const char **l = lengths; |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 401 | const u_int *s = seconds; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 402 | |
| 403 | if (secs == 0) { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 404 | ND_PRINT((ndo, "0s")); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 405 | return; |
| 406 | } |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 407 | while (secs > 0) { |
| 408 | if (secs >= *s) { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 409 | ND_PRINT((ndo, "%d%s", secs / *s, *l)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 410 | secs -= (secs / *s) * *s; |
| 411 | } |
| 412 | s++; |
| 413 | l++; |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | /* |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 418 | * Print a signed relative number of seconds (e.g. hold time, prune timer) |
| 419 | * in the form 5m1s. This does no truncation, so 32230861 seconds |
| 420 | * is represented as 1y1w1d1h1m1s. |
| 421 | */ |
| 422 | void |
| 423 | signed_relts_print(netdissect_options *ndo, |
| 424 | int32_t secs) |
| 425 | { |
| 426 | if (secs < 0) { |
| 427 | ND_PRINT((ndo, "-")); |
| 428 | if (secs == INT32_MIN) { |
| 429 | /* |
| 430 | * -2^31; you can't fit its absolute value into |
| 431 | * a 32-bit signed integer. |
| 432 | * |
| 433 | * Just directly pass said absolute value to |
| 434 | * unsigned_relts_print() directly. |
| 435 | * |
| 436 | * (XXX - does ISO C guarantee that -(-2^n), |
| 437 | * when calculated and cast to an n-bit unsigned |
| 438 | * integer type, will have the value 2^n?) |
| 439 | */ |
| 440 | unsigned_relts_print(ndo, 2147483648U); |
| 441 | } else { |
| 442 | /* |
| 443 | * We now know -secs will fit into an int32_t; |
| 444 | * negate it and pass that to unsigned_relts_print(). |
| 445 | */ |
| 446 | unsigned_relts_print(ndo, -secs); |
| 447 | } |
| 448 | return; |
| 449 | } |
| 450 | unsigned_relts_print(ndo, secs); |
| 451 | } |
| 452 | |
| 453 | /* |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 454 | * this is a generic routine for printing unknown data; |
| 455 | * we pass on the linefeed plus indentation string to |
| 456 | * get a proper output - returns 0 on error |
| 457 | */ |
| 458 | |
| 459 | int |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 460 | print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 461 | { |
| 462 | if (len < 0) { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 463 | ND_PRINT((ndo,"%sDissector error: print_unknown_data called with negative length", |
| 464 | ident)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 465 | return(0); |
| 466 | } |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 467 | if (ndo->ndo_snapend - cp < len) |
| 468 | len = ndo->ndo_snapend - cp; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 469 | if (len < 0) { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 470 | ND_PRINT((ndo,"%sDissector error: print_unknown_data called with pointer past end of packet", |
| 471 | ident)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 472 | return(0); |
| 473 | } |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 474 | hex_print(ndo, ident,cp,len); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 475 | return(1); /* everything is ok */ |
| 476 | } |
| 477 | |
| 478 | /* |
| 479 | * Convert a token value to a string; use "fmt" if not found. |
| 480 | */ |
| 481 | const char * |
| 482 | tok2strbuf(register const struct tok *lp, register const char *fmt, |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 483 | register u_int v, char *buf, size_t bufsize) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 484 | { |
| 485 | if (lp != NULL) { |
| 486 | while (lp->s != NULL) { |
| 487 | if (lp->v == v) |
| 488 | return (lp->s); |
| 489 | ++lp; |
| 490 | } |
| 491 | } |
| 492 | if (fmt == NULL) |
| 493 | fmt = "#%d"; |
| 494 | |
| 495 | (void)snprintf(buf, bufsize, fmt, v); |
| 496 | return (const char *)buf; |
| 497 | } |
| 498 | |
| 499 | /* |
| 500 | * Convert a token value to a string; use "fmt" if not found. |
| 501 | */ |
| 502 | const char * |
| 503 | tok2str(register const struct tok *lp, register const char *fmt, |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 504 | register u_int v) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 505 | { |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 506 | static char buf[4][TOKBUFSIZE]; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 507 | static int idx = 0; |
| 508 | char *ret; |
| 509 | |
| 510 | ret = buf[idx]; |
| 511 | idx = (idx+1) & 3; |
| 512 | return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0])); |
| 513 | } |
| 514 | |
| 515 | /* |
| 516 | * Convert a bit token value to a string; use "fmt" if not found. |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 517 | * this is useful for parsing bitfields, the output strings are seperated |
| 518 | * if the s field is positive. |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 519 | */ |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 520 | static char * |
| 521 | bittok2str_internal(register const struct tok *lp, register const char *fmt, |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 522 | register u_int v, const char *sep) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 523 | { |
Elliott Hughes | cec480a | 2017-12-19 16:54:57 -0800 | [diff] [blame] | 524 | static char buf[1024+1]; /* our string buffer */ |
| 525 | char *bufp = buf; |
| 526 | size_t space_left = sizeof(buf), string_size; |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 527 | register u_int rotbit; /* this is the bit we rotate through all bitpositions */ |
| 528 | register u_int tokval; |
| 529 | const char * sepstr = ""; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 530 | |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 531 | while (lp != NULL && lp->s != NULL) { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 532 | tokval=lp->v; /* load our first value */ |
| 533 | rotbit=1; |
| 534 | while (rotbit != 0) { |
| 535 | /* |
| 536 | * lets AND the rotating bit with our token value |
| 537 | * and see if we have got a match |
| 538 | */ |
| 539 | if (tokval == (v&rotbit)) { |
| 540 | /* ok we have found something */ |
Elliott Hughes | cec480a | 2017-12-19 16:54:57 -0800 | [diff] [blame] | 541 | if (space_left <= 1) |
| 542 | return (buf); /* only enough room left for NUL, if that */ |
| 543 | string_size = strlcpy(bufp, sepstr, space_left); |
| 544 | if (string_size >= space_left) |
| 545 | return (buf); /* we ran out of room */ |
| 546 | bufp += string_size; |
| 547 | space_left -= string_size; |
| 548 | if (space_left <= 1) |
| 549 | return (buf); /* only enough room left for NUL, if that */ |
| 550 | string_size = strlcpy(bufp, lp->s, space_left); |
| 551 | if (string_size >= space_left) |
| 552 | return (buf); /* we ran out of room */ |
| 553 | bufp += string_size; |
| 554 | space_left -= string_size; |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 555 | sepstr = sep; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 556 | break; |
| 557 | } |
| 558 | rotbit=rotbit<<1; /* no match - lets shift and try again */ |
| 559 | } |
| 560 | lp++; |
| 561 | } |
| 562 | |
Elliott Hughes | cec480a | 2017-12-19 16:54:57 -0800 | [diff] [blame] | 563 | if (bufp == buf) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 564 | /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */ |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 565 | (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : fmt, v); |
| 566 | return (buf); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 567 | } |
| 568 | |
| 569 | /* |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 570 | * Convert a bit token value to a string; use "fmt" if not found. |
| 571 | * this is useful for parsing bitfields, the output strings are not seperated. |
| 572 | */ |
| 573 | char * |
| 574 | bittok2str_nosep(register const struct tok *lp, register const char *fmt, |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 575 | register u_int v) |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 576 | { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 577 | return (bittok2str_internal(lp, fmt, v, "")); |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 578 | } |
| 579 | |
| 580 | /* |
| 581 | * Convert a bit token value to a string; use "fmt" if not found. |
| 582 | * this is useful for parsing bitfields, the output strings are comma seperated. |
| 583 | */ |
| 584 | char * |
| 585 | bittok2str(register const struct tok *lp, register const char *fmt, |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 586 | register u_int v) |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 587 | { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 588 | return (bittok2str_internal(lp, fmt, v, ", ")); |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 589 | } |
| 590 | |
| 591 | /* |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 592 | * Convert a value to a string using an array; the macro |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 593 | * tok2strary() in <netdissect.h> is the public interface to |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 594 | * this function and ensures that the second argument is |
| 595 | * correct for bounds-checking. |
| 596 | */ |
| 597 | const char * |
| 598 | tok2strary_internal(register const char **lp, int n, register const char *fmt, |
| 599 | register int v) |
| 600 | { |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 601 | static char buf[TOKBUFSIZE]; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 602 | |
| 603 | if (v >= 0 && v < n && lp[v] != NULL) |
| 604 | return lp[v]; |
| 605 | if (fmt == NULL) |
| 606 | fmt = "#%d"; |
| 607 | (void)snprintf(buf, sizeof(buf), fmt, v); |
| 608 | return (buf); |
| 609 | } |
| 610 | |
| 611 | /* |
| 612 | * Convert a 32-bit netmask to prefixlen if possible |
| 613 | * the function returns the prefix-len; if plen == -1 |
| 614 | * then conversion was not possible; |
| 615 | */ |
| 616 | |
| 617 | int |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 618 | mask2plen(uint32_t mask) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 619 | { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 620 | uint32_t bitmasks[33] = { |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 621 | 0x00000000, |
| 622 | 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, |
| 623 | 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, |
| 624 | 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, |
| 625 | 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, |
| 626 | 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, |
| 627 | 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, |
| 628 | 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, |
| 629 | 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff |
| 630 | }; |
| 631 | int prefix_len = 32; |
| 632 | |
| 633 | /* let's see if we can transform the mask into a prefixlen */ |
| 634 | while (prefix_len >= 0) { |
| 635 | if (bitmasks[prefix_len] == mask) |
| 636 | break; |
| 637 | prefix_len--; |
| 638 | } |
| 639 | return (prefix_len); |
| 640 | } |
| 641 | |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 642 | int |
| 643 | mask62plen(const u_char *mask) |
| 644 | { |
| 645 | u_char bitmasks[9] = { |
| 646 | 0x00, |
| 647 | 0x80, 0xc0, 0xe0, 0xf0, |
| 648 | 0xf8, 0xfc, 0xfe, 0xff |
| 649 | }; |
| 650 | int byte; |
| 651 | int cidr_len = 0; |
| 652 | |
| 653 | for (byte = 0; byte < 16; byte++) { |
| 654 | u_int bits; |
| 655 | |
| 656 | for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) { |
| 657 | if (mask[byte] == bitmasks[bits]) { |
| 658 | cidr_len += bits; |
| 659 | break; |
| 660 | } |
| 661 | } |
| 662 | |
| 663 | if (mask[byte] != 0xff) |
| 664 | break; |
| 665 | } |
| 666 | return (cidr_len); |
| 667 | } |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 668 | |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 669 | /* |
| 670 | * Routine to print out information for text-based protocols such as FTP, |
| 671 | * HTTP, SMTP, RTSP, SIP, .... |
| 672 | */ |
| 673 | #define MAX_TOKEN 128 |
| 674 | |
| 675 | /* |
| 676 | * Fetch a token from a packet, starting at the specified index, |
| 677 | * and return the length of the token. |
| 678 | * |
| 679 | * Returns 0 on error; yes, this is indistinguishable from an empty |
| 680 | * token, but an "empty token" isn't a valid token - it just means |
| 681 | * either a space character at the beginning of the line (this |
| 682 | * includes a blank line) or no more tokens remaining on the line. |
| 683 | */ |
| 684 | static int |
| 685 | fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len, |
| 686 | u_char *tbuf, size_t tbuflen) |
| 687 | { |
| 688 | size_t toklen = 0; |
| 689 | |
| 690 | for (; idx < len; idx++) { |
| 691 | if (!ND_TTEST(*(pptr + idx))) { |
| 692 | /* ran past end of captured data */ |
| 693 | return (0); |
| 694 | } |
| 695 | if (!isascii(*(pptr + idx))) { |
| 696 | /* not an ASCII character */ |
| 697 | return (0); |
| 698 | } |
| 699 | if (isspace(*(pptr + idx))) { |
| 700 | /* end of token */ |
| 701 | break; |
| 702 | } |
| 703 | if (!isprint(*(pptr + idx))) { |
| 704 | /* not part of a command token or response code */ |
| 705 | return (0); |
| 706 | } |
| 707 | if (toklen + 2 > tbuflen) { |
| 708 | /* no room for this character and terminating '\0' */ |
| 709 | return (0); |
| 710 | } |
| 711 | tbuf[toklen] = *(pptr + idx); |
| 712 | toklen++; |
| 713 | } |
| 714 | if (toklen == 0) { |
| 715 | /* no token */ |
| 716 | return (0); |
| 717 | } |
| 718 | tbuf[toklen] = '\0'; |
| 719 | |
| 720 | /* |
| 721 | * Skip past any white space after the token, until we see |
| 722 | * an end-of-line (CR or LF). |
| 723 | */ |
| 724 | for (; idx < len; idx++) { |
| 725 | if (!ND_TTEST(*(pptr + idx))) { |
| 726 | /* ran past end of captured data */ |
| 727 | break; |
| 728 | } |
| 729 | if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') { |
| 730 | /* end of line */ |
| 731 | break; |
| 732 | } |
| 733 | if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) { |
| 734 | /* not a printable ASCII character */ |
| 735 | break; |
| 736 | } |
| 737 | if (!isspace(*(pptr + idx))) { |
| 738 | /* beginning of next token */ |
| 739 | break; |
| 740 | } |
| 741 | } |
| 742 | return (idx); |
| 743 | } |
| 744 | |
| 745 | /* |
| 746 | * Scan a buffer looking for a line ending - LF or CR-LF. |
| 747 | * Return the index of the character after the line ending or 0 if |
| 748 | * we encounter a non-ASCII or non-printable character or don't find |
| 749 | * the line ending. |
| 750 | */ |
| 751 | static u_int |
| 752 | print_txt_line(netdissect_options *ndo, const char *protoname, |
| 753 | const char *prefix, const u_char *pptr, u_int idx, u_int len) |
| 754 | { |
| 755 | u_int startidx; |
| 756 | u_int linelen; |
| 757 | |
| 758 | startidx = idx; |
| 759 | while (idx < len) { |
| 760 | ND_TCHECK(*(pptr+idx)); |
| 761 | if (*(pptr+idx) == '\n') { |
| 762 | /* |
| 763 | * LF without CR; end of line. |
| 764 | * Skip the LF and print the line, with the |
| 765 | * exception of the LF. |
| 766 | */ |
| 767 | linelen = idx - startidx; |
| 768 | idx++; |
| 769 | goto print; |
| 770 | } else if (*(pptr+idx) == '\r') { |
| 771 | /* CR - any LF? */ |
| 772 | if ((idx+1) >= len) { |
| 773 | /* not in this packet */ |
| 774 | return (0); |
| 775 | } |
| 776 | ND_TCHECK(*(pptr+idx+1)); |
| 777 | if (*(pptr+idx+1) == '\n') { |
| 778 | /* |
| 779 | * CR-LF; end of line. |
| 780 | * Skip the CR-LF and print the line, with |
| 781 | * the exception of the CR-LF. |
| 782 | */ |
| 783 | linelen = idx - startidx; |
| 784 | idx += 2; |
| 785 | goto print; |
| 786 | } |
| 787 | |
| 788 | /* |
| 789 | * CR followed by something else; treat this |
| 790 | * as if it were binary data, and don't print |
| 791 | * it. |
| 792 | */ |
| 793 | return (0); |
| 794 | } else if (!isascii(*(pptr+idx)) || |
| 795 | (!isprint(*(pptr+idx)) && *(pptr+idx) != '\t')) { |
| 796 | /* |
| 797 | * Not a printable ASCII character and not a tab; |
| 798 | * treat this as if it were binary data, and |
| 799 | * don't print it. |
| 800 | */ |
| 801 | return (0); |
| 802 | } |
| 803 | idx++; |
| 804 | } |
| 805 | |
| 806 | /* |
| 807 | * All printable ASCII, but no line ending after that point |
| 808 | * in the buffer; treat this as if it were truncated. |
| 809 | */ |
| 810 | trunc: |
| 811 | linelen = idx - startidx; |
| 812 | ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx, |
| 813 | protoname)); |
| 814 | return (0); |
| 815 | |
| 816 | print: |
| 817 | ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx)); |
| 818 | return (idx); |
| 819 | } |
| 820 | |
| 821 | void |
| 822 | txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len, |
| 823 | const char *protoname, const char **cmds, u_int flags) |
| 824 | { |
| 825 | u_int idx, eol; |
| 826 | u_char token[MAX_TOKEN+1]; |
| 827 | const char *cmd; |
| 828 | int is_reqresp = 0; |
| 829 | const char *pnp; |
| 830 | |
| 831 | if (cmds != NULL) { |
| 832 | /* |
| 833 | * This protocol has more than just request and |
| 834 | * response lines; see whether this looks like a |
| 835 | * request or response. |
| 836 | */ |
| 837 | idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token)); |
| 838 | if (idx != 0) { |
| 839 | /* Is this a valid request name? */ |
| 840 | while ((cmd = *cmds++) != NULL) { |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 841 | if (ascii_strcasecmp((const char *)token, cmd) == 0) { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 842 | /* Yes. */ |
| 843 | is_reqresp = 1; |
| 844 | break; |
| 845 | } |
| 846 | } |
| 847 | |
| 848 | /* |
| 849 | * No - is this a valid response code (3 digits)? |
| 850 | * |
| 851 | * Is this token the response code, or is the next |
| 852 | * token the response code? |
| 853 | */ |
| 854 | if (flags & RESP_CODE_SECOND_TOKEN) { |
| 855 | /* |
| 856 | * Next token - get it. |
| 857 | */ |
| 858 | idx = fetch_token(ndo, pptr, idx, len, token, |
| 859 | sizeof(token)); |
| 860 | } |
| 861 | if (idx != 0) { |
| 862 | if (isdigit(token[0]) && isdigit(token[1]) && |
| 863 | isdigit(token[2]) && token[3] == '\0') { |
| 864 | /* Yes. */ |
| 865 | is_reqresp = 1; |
| 866 | } |
| 867 | } |
| 868 | } |
| 869 | } else { |
| 870 | /* |
| 871 | * This protocol has only request and response lines |
| 872 | * (e.g., FTP, where all the data goes over a |
| 873 | * different connection); assume the payload is |
| 874 | * a request or response. |
| 875 | */ |
| 876 | is_reqresp = 1; |
| 877 | } |
| 878 | |
| 879 | /* Capitalize the protocol name */ |
| 880 | for (pnp = protoname; *pnp != '\0'; pnp++) |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 881 | ND_PRINT((ndo, "%c", toupper((u_char)*pnp))); |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 882 | |
| 883 | if (is_reqresp) { |
| 884 | /* |
| 885 | * In non-verbose mode, just print the protocol, followed |
| 886 | * by the first line as the request or response info. |
| 887 | * |
| 888 | * In verbose mode, print lines as text until we run out |
| 889 | * of characters or see something that's not a |
| 890 | * printable-ASCII line. |
| 891 | */ |
| 892 | if (ndo->ndo_vflag) { |
| 893 | /* |
| 894 | * We're going to print all the text lines in the |
| 895 | * request or response; just print the length |
| 896 | * on the first line of the output. |
| 897 | */ |
| 898 | ND_PRINT((ndo, ", length: %u", len)); |
| 899 | for (idx = 0; |
| 900 | idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0; |
| 901 | idx = eol) |
| 902 | ; |
| 903 | } else { |
| 904 | /* |
| 905 | * Just print the first text line. |
| 906 | */ |
| 907 | print_txt_line(ndo, protoname, ": ", pptr, 0, len); |
| 908 | } |
| 909 | } |
| 910 | } |
| 911 | |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 912 | void |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 913 | safeputs(netdissect_options *ndo, |
| 914 | const u_char *s, const u_int maxlen) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 915 | { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 916 | u_int idx = 0; |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 917 | |
Elliott Hughes | cec480a | 2017-12-19 16:54:57 -0800 | [diff] [blame] | 918 | while (idx < maxlen && *s) { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 919 | safeputchar(ndo, *s); |
| 920 | idx++; |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 921 | s++; |
| 922 | } |
| 923 | } |
| 924 | |
| 925 | void |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 926 | safeputchar(netdissect_options *ndo, |
| 927 | const u_char c) |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 928 | { |
Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 929 | ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c)); |
The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 930 | } |
JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 931 | |
| 932 | #ifdef LBL_ALIGN |
| 933 | /* |
| 934 | * Some compilers try to optimize memcpy(), using the alignment constraint |
| 935 | * on the argument pointer type. by using this function, we try to avoid the |
| 936 | * optimization. |
| 937 | */ |
| 938 | void |
| 939 | unaligned_memcpy(void *p, const void *q, size_t l) |
| 940 | { |
| 941 | memcpy(p, q, l); |
| 942 | } |
| 943 | |
| 944 | /* As with memcpy(), so with memcmp(). */ |
| 945 | int |
| 946 | unaligned_memcmp(const void *p, const void *q, size_t l) |
| 947 | { |
| 948 | return (memcmp(p, q, l)); |
| 949 | } |
| 950 | #endif |
Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 951 | |