print-ip.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /*
  2. * Copyright (c) 1988, 1989, 1990, 1991, 1992, 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. /* \summary: IP printer */
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #include <netdissect-stdinc.h>
  26. #include <string.h>
  27. #include "netdissect.h"
  28. #include "addrtoname.h"
  29. #include "extract.h"
  30. #include "ip.h"
  31. #include "ipproto.h"
  32. static const char tstr[] = "[|ip]";
  33. static const struct tok ip_option_values[] = {
  34. { IPOPT_EOL, "EOL" },
  35. { IPOPT_NOP, "NOP" },
  36. { IPOPT_TS, "timestamp" },
  37. { IPOPT_SECURITY, "security" },
  38. { IPOPT_RR, "RR" },
  39. { IPOPT_SSRR, "SSRR" },
  40. { IPOPT_LSRR, "LSRR" },
  41. { IPOPT_RA, "RA" },
  42. { IPOPT_RFC1393, "traceroute" },
  43. { 0, NULL }
  44. };
  45. /*
  46. * print the recorded route in an IP RR, LSRR or SSRR option.
  47. */
  48. static int
  49. ip_printroute(netdissect_options *ndo,
  50. register const u_char *cp, u_int length)
  51. {
  52. register u_int ptr;
  53. register u_int len;
  54. if (length < 3) {
  55. ND_PRINT((ndo, " [bad length %u]", length));
  56. return (0);
  57. }
  58. if ((length + 1) & 3)
  59. ND_PRINT((ndo, " [bad length %u]", length));
  60. ND_TCHECK(cp[2]);
  61. ptr = cp[2] - 1;
  62. if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
  63. ND_PRINT((ndo, " [bad ptr %u]", cp[2]));
  64. for (len = 3; len < length; len += 4) {
  65. ND_TCHECK2(cp[len], 4);
  66. ND_PRINT((ndo, " %s", ipaddr_string(ndo, &cp[len])));
  67. if (ptr > len)
  68. ND_PRINT((ndo, ","));
  69. }
  70. return (0);
  71. trunc:
  72. return (-1);
  73. }
  74. /*
  75. * If source-routing is present and valid, return the final destination.
  76. * Otherwise, return IP destination.
  77. *
  78. * This is used for UDP and TCP pseudo-header in the checksum
  79. * calculation.
  80. */
  81. static uint32_t
  82. ip_finddst(netdissect_options *ndo,
  83. const struct ip *ip)
  84. {
  85. int length;
  86. int len;
  87. const u_char *cp;
  88. uint32_t retval;
  89. cp = (const u_char *)(ip + 1);
  90. length = (IP_HL(ip) << 2) - sizeof(struct ip);
  91. for (; length > 0; cp += len, length -= len) {
  92. int tt;
  93. ND_TCHECK(*cp);
  94. tt = *cp;
  95. if (tt == IPOPT_EOL)
  96. break;
  97. else if (tt == IPOPT_NOP)
  98. len = 1;
  99. else {
  100. ND_TCHECK(cp[1]);
  101. len = cp[1];
  102. if (len < 2)
  103. break;
  104. }
  105. ND_TCHECK2(*cp, len);
  106. switch (tt) {
  107. case IPOPT_SSRR:
  108. case IPOPT_LSRR:
  109. if (len < 7)
  110. break;
  111. UNALIGNED_MEMCPY(&retval, cp + len - 4, 4);
  112. return retval;
  113. }
  114. }
  115. trunc:
  116. UNALIGNED_MEMCPY(&retval, &ip->ip_dst, sizeof(uint32_t));
  117. return retval;
  118. }
  119. /*
  120. * Compute a V4-style checksum by building a pseudoheader.
  121. */
  122. int
  123. nextproto4_cksum(netdissect_options *ndo,
  124. const struct ip *ip, const uint8_t *data,
  125. u_int len, u_int covlen, u_int next_proto)
  126. {
  127. struct phdr {
  128. uint32_t src;
  129. uint32_t dst;
  130. u_char mbz;
  131. u_char proto;
  132. uint16_t len;
  133. } ph;
  134. struct cksum_vec vec[2];
  135. /* pseudo-header.. */
  136. ph.len = htons((uint16_t)len);
  137. ph.mbz = 0;
  138. ph.proto = next_proto;
  139. UNALIGNED_MEMCPY(&ph.src, &ip->ip_src, sizeof(uint32_t));
  140. if (IP_HL(ip) == 5)
  141. UNALIGNED_MEMCPY(&ph.dst, &ip->ip_dst, sizeof(uint32_t));
  142. else
  143. ph.dst = ip_finddst(ndo, ip);
  144. vec[0].ptr = (const uint8_t *)(void *)&ph;
  145. vec[0].len = sizeof(ph);
  146. vec[1].ptr = data;
  147. vec[1].len = covlen;
  148. return (in_cksum(vec, 2));
  149. }
  150. static int
  151. ip_printts(netdissect_options *ndo,
  152. register const u_char *cp, u_int length)
  153. {
  154. register u_int ptr;
  155. register u_int len;
  156. int hoplen;
  157. const char *type;
  158. if (length < 4) {
  159. ND_PRINT((ndo, "[bad length %u]", length));
  160. return (0);
  161. }
  162. ND_PRINT((ndo, " TS{"));
  163. hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
  164. if ((length - 4) & (hoplen-1))
  165. ND_PRINT((ndo, "[bad length %u]", length));
  166. ND_TCHECK(cp[2]);
  167. ptr = cp[2] - 1;
  168. len = 0;
  169. if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
  170. ND_PRINT((ndo, "[bad ptr %u]", cp[2]));
  171. ND_TCHECK(cp[3]);
  172. switch (cp[3]&0xF) {
  173. case IPOPT_TS_TSONLY:
  174. ND_PRINT((ndo, "TSONLY"));
  175. break;
  176. case IPOPT_TS_TSANDADDR:
  177. ND_PRINT((ndo, "TS+ADDR"));
  178. break;
  179. /*
  180. * prespecified should really be 3, but some ones might send 2
  181. * instead, and the IPOPT_TS_PRESPEC constant can apparently
  182. * have both values, so we have to hard-code it here.
  183. */
  184. case 2:
  185. ND_PRINT((ndo, "PRESPEC2.0"));
  186. break;
  187. case 3: /* IPOPT_TS_PRESPEC */
  188. ND_PRINT((ndo, "PRESPEC"));
  189. break;
  190. default:
  191. ND_PRINT((ndo, "[bad ts type %d]", cp[3]&0xF));
  192. goto done;
  193. }
  194. type = " ";
  195. for (len = 4; len < length; len += hoplen) {
  196. if (ptr == len)
  197. type = " ^ ";
  198. ND_TCHECK2(cp[len], hoplen);
  199. ND_PRINT((ndo, "%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
  200. hoplen!=8 ? "" : ipaddr_string(ndo, &cp[len])));
  201. type = " ";
  202. }
  203. done:
  204. ND_PRINT((ndo, "%s", ptr == len ? " ^ " : ""));
  205. if (cp[3]>>4)
  206. ND_PRINT((ndo, " [%d hops not recorded]} ", cp[3]>>4));
  207. else
  208. ND_PRINT((ndo, "}"));
  209. return (0);
  210. trunc:
  211. return (-1);
  212. }
  213. /*
  214. * print IP options.
  215. */
  216. static void
  217. ip_optprint(netdissect_options *ndo,
  218. register const u_char *cp, u_int length)
  219. {
  220. register u_int option_len;
  221. const char *sep = "";
  222. for (; length > 0; cp += option_len, length -= option_len) {
  223. u_int option_code;
  224. ND_PRINT((ndo, "%s", sep));
  225. sep = ",";
  226. ND_TCHECK(*cp);
  227. option_code = *cp;
  228. ND_PRINT((ndo, "%s",
  229. tok2str(ip_option_values,"unknown %u",option_code)));
  230. if (option_code == IPOPT_NOP ||
  231. option_code == IPOPT_EOL)
  232. option_len = 1;
  233. else {
  234. ND_TCHECK(cp[1]);
  235. option_len = cp[1];
  236. if (option_len < 2) {
  237. ND_PRINT((ndo, " [bad length %u]", option_len));
  238. return;
  239. }
  240. }
  241. if (option_len > length) {
  242. ND_PRINT((ndo, " [bad length %u]", option_len));
  243. return;
  244. }
  245. ND_TCHECK2(*cp, option_len);
  246. switch (option_code) {
  247. case IPOPT_EOL:
  248. return;
  249. case IPOPT_TS:
  250. if (ip_printts(ndo, cp, option_len) == -1)
  251. goto trunc;
  252. break;
  253. case IPOPT_RR: /* fall through */
  254. case IPOPT_SSRR:
  255. case IPOPT_LSRR:
  256. if (ip_printroute(ndo, cp, option_len) == -1)
  257. goto trunc;
  258. break;
  259. case IPOPT_RA:
  260. if (option_len < 4) {
  261. ND_PRINT((ndo, " [bad length %u]", option_len));
  262. break;
  263. }
  264. ND_TCHECK(cp[3]);
  265. if (EXTRACT_16BITS(&cp[2]) != 0)
  266. ND_PRINT((ndo, " value %u", EXTRACT_16BITS(&cp[2])));
  267. break;
  268. case IPOPT_NOP: /* nothing to print - fall through */
  269. case IPOPT_SECURITY:
  270. default:
  271. break;
  272. }
  273. }
  274. return;
  275. trunc:
  276. ND_PRINT((ndo, "%s", tstr));
  277. }
  278. #define IP_RES 0x8000
  279. static const struct tok ip_frag_values[] = {
  280. { IP_MF, "+" },
  281. { IP_DF, "DF" },
  282. { IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */
  283. { 0, NULL }
  284. };
  285. struct ip_print_demux_state {
  286. const struct ip *ip;
  287. const u_char *cp;
  288. u_int len, off;
  289. u_char nh;
  290. int advance;
  291. };
  292. static void
  293. ip_print_demux(netdissect_options *ndo,
  294. struct ip_print_demux_state *ipds)
  295. {
  296. const char *p_name;
  297. again:
  298. switch (ipds->nh) {
  299. case IPPROTO_AH:
  300. if (!ND_TTEST(*ipds->cp)) {
  301. ND_PRINT((ndo, "[|AH]"));
  302. break;
  303. }
  304. ipds->nh = *ipds->cp;
  305. ipds->advance = ah_print(ndo, ipds->cp);
  306. if (ipds->advance <= 0)
  307. break;
  308. ipds->cp += ipds->advance;
  309. ipds->len -= ipds->advance;
  310. goto again;
  311. case IPPROTO_ESP:
  312. {
  313. int enh, padlen;
  314. ipds->advance = esp_print(ndo, ipds->cp, ipds->len,
  315. (const u_char *)ipds->ip,
  316. &enh, &padlen);
  317. if (ipds->advance <= 0)
  318. break;
  319. ipds->cp += ipds->advance;
  320. ipds->len -= ipds->advance + padlen;
  321. ipds->nh = enh & 0xff;
  322. goto again;
  323. }
  324. case IPPROTO_IPCOMP:
  325. {
  326. ipcomp_print(ndo, ipds->cp);
  327. /*
  328. * Either this has decompressed the payload and
  329. * printed it, in which case there's nothing more
  330. * to do, or it hasn't, in which case there's
  331. * nothing more to do.
  332. */
  333. break;
  334. }
  335. case IPPROTO_SCTP:
  336. sctp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len);
  337. break;
  338. case IPPROTO_DCCP:
  339. dccp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len);
  340. break;
  341. case IPPROTO_TCP:
  342. /* pass on the MF bit plus the offset to detect fragments */
  343. tcp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
  344. ipds->off & (IP_MF|IP_OFFMASK));
  345. break;
  346. case IPPROTO_UDP:
  347. /* pass on the MF bit plus the offset to detect fragments */
  348. udp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
  349. ipds->off & (IP_MF|IP_OFFMASK));
  350. break;
  351. case IPPROTO_ICMP:
  352. /* pass on the MF bit plus the offset to detect fragments */
  353. icmp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip,
  354. ipds->off & (IP_MF|IP_OFFMASK));
  355. break;
  356. case IPPROTO_PIGP:
  357. /*
  358. * XXX - the current IANA protocol number assignments
  359. * page lists 9 as "any private interior gateway
  360. * (used by Cisco for their IGRP)" and 88 as
  361. * "EIGRP" from Cisco.
  362. *
  363. * Recent BSD <netinet/in.h> headers define
  364. * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
  365. * We define IP_PROTO_PIGP as 9 and
  366. * IP_PROTO_EIGRP as 88; those names better
  367. * match was the current protocol number
  368. * assignments say.
  369. */
  370. igrp_print(ndo, ipds->cp, ipds->len);
  371. break;
  372. case IPPROTO_EIGRP:
  373. eigrp_print(ndo, ipds->cp, ipds->len);
  374. break;
  375. case IPPROTO_ND:
  376. ND_PRINT((ndo, " nd %d", ipds->len));
  377. break;
  378. case IPPROTO_EGP:
  379. egp_print(ndo, ipds->cp, ipds->len);
  380. break;
  381. case IPPROTO_OSPF:
  382. ospf_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
  383. break;
  384. case IPPROTO_IGMP:
  385. igmp_print(ndo, ipds->cp, ipds->len);
  386. break;
  387. case IPPROTO_IPV4:
  388. /* DVMRP multicast tunnel (ip-in-ip encapsulation) */
  389. ip_print(ndo, ipds->cp, ipds->len);
  390. if (! ndo->ndo_vflag) {
  391. ND_PRINT((ndo, " (ipip-proto-4)"));
  392. return;
  393. }
  394. break;
  395. case IPPROTO_IPV6:
  396. /* ip6-in-ip encapsulation */
  397. ip6_print(ndo, ipds->cp, ipds->len);
  398. break;
  399. case IPPROTO_RSVP:
  400. rsvp_print(ndo, ipds->cp, ipds->len);
  401. break;
  402. case IPPROTO_GRE:
  403. /* do it */
  404. gre_print(ndo, ipds->cp, ipds->len);
  405. break;
  406. case IPPROTO_MOBILE:
  407. mobile_print(ndo, ipds->cp, ipds->len);
  408. break;
  409. case IPPROTO_PIM:
  410. pim_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
  411. break;
  412. case IPPROTO_VRRP:
  413. if (ndo->ndo_packettype == PT_CARP) {
  414. if (ndo->ndo_vflag)
  415. ND_PRINT((ndo, "carp %s > %s: ",
  416. ipaddr_string(ndo, &ipds->ip->ip_src),
  417. ipaddr_string(ndo, &ipds->ip->ip_dst)));
  418. carp_print(ndo, ipds->cp, ipds->len, ipds->ip->ip_ttl);
  419. } else {
  420. if (ndo->ndo_vflag)
  421. ND_PRINT((ndo, "vrrp %s > %s: ",
  422. ipaddr_string(ndo, &ipds->ip->ip_src),
  423. ipaddr_string(ndo, &ipds->ip->ip_dst)));
  424. vrrp_print(ndo, ipds->cp, ipds->len,
  425. (const u_char *)ipds->ip, ipds->ip->ip_ttl);
  426. }
  427. break;
  428. case IPPROTO_PGM:
  429. pgm_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip);
  430. break;
  431. default:
  432. if (ndo->ndo_nflag==0 && (p_name = netdb_protoname(ipds->nh)) != NULL)
  433. ND_PRINT((ndo, " %s", p_name));
  434. else
  435. ND_PRINT((ndo, " ip-proto-%d", ipds->nh));
  436. ND_PRINT((ndo, " %d", ipds->len));
  437. break;
  438. }
  439. }
  440. void
  441. ip_print_inner(netdissect_options *ndo,
  442. const u_char *bp,
  443. u_int length, u_int nh,
  444. const u_char *bp2)
  445. {
  446. struct ip_print_demux_state ipd;
  447. ipd.ip = (const struct ip *)bp2;
  448. ipd.cp = bp;
  449. ipd.len = length;
  450. ipd.off = 0;
  451. ipd.nh = nh;
  452. ipd.advance = 0;
  453. ip_print_demux(ndo, &ipd);
  454. }
  455. /*
  456. * print an IP datagram.
  457. */
  458. void
  459. ip_print(netdissect_options *ndo,
  460. const u_char *bp,
  461. u_int length)
  462. {
  463. struct ip_print_demux_state ipd;
  464. struct ip_print_demux_state *ipds=&ipd;
  465. const u_char *ipend;
  466. u_int hlen;
  467. struct cksum_vec vec[1];
  468. uint16_t sum, ip_sum;
  469. const char *p_name;
  470. ipds->ip = (const struct ip *)bp;
  471. ND_TCHECK(ipds->ip->ip_vhl);
  472. if (IP_V(ipds->ip) != 4) { /* print version and fail if != 4 */
  473. if (IP_V(ipds->ip) == 6)
  474. ND_PRINT((ndo, "IP6, wrong link-layer encapsulation "));
  475. else
  476. ND_PRINT((ndo, "IP%u ", IP_V(ipds->ip)));
  477. return;
  478. }
  479. if (!ndo->ndo_eflag)
  480. ND_PRINT((ndo, "IP "));
  481. ND_TCHECK(*ipds->ip);
  482. if (length < sizeof (struct ip)) {
  483. ND_PRINT((ndo, "truncated-ip %u", length));
  484. return;
  485. }
  486. hlen = IP_HL(ipds->ip) * 4;
  487. if (hlen < sizeof (struct ip)) {
  488. ND_PRINT((ndo, "bad-hlen %u", hlen));
  489. return;
  490. }
  491. ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len);
  492. if (length < ipds->len)
  493. ND_PRINT((ndo, "truncated-ip - %u bytes missing! ",
  494. ipds->len - length));
  495. if (ipds->len < hlen) {
  496. #ifdef GUESS_TSO
  497. if (ipds->len) {
  498. ND_PRINT((ndo, "bad-len %u", ipds->len));
  499. return;
  500. }
  501. else {
  502. /* we guess that it is a TSO send */
  503. ipds->len = length;
  504. }
  505. #else
  506. ND_PRINT((ndo, "bad-len %u", ipds->len));
  507. return;
  508. #endif /* GUESS_TSO */
  509. }
  510. /*
  511. * Cut off the snapshot length to the end of the IP payload.
  512. */
  513. ipend = bp + ipds->len;
  514. if (ipend < ndo->ndo_snapend)
  515. ndo->ndo_snapend = ipend;
  516. ipds->len -= hlen;
  517. ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off);
  518. if (ndo->ndo_vflag) {
  519. ND_PRINT((ndo, "(tos 0x%x", (int)ipds->ip->ip_tos));
  520. /* ECN bits */
  521. switch (ipds->ip->ip_tos & 0x03) {
  522. case 0:
  523. break;
  524. case 1:
  525. ND_PRINT((ndo, ",ECT(1)"));
  526. break;
  527. case 2:
  528. ND_PRINT((ndo, ",ECT(0)"));
  529. break;
  530. case 3:
  531. ND_PRINT((ndo, ",CE"));
  532. break;
  533. }
  534. if (ipds->ip->ip_ttl >= 1)
  535. ND_PRINT((ndo, ", ttl %u", ipds->ip->ip_ttl));
  536. /*
  537. * for the firewall guys, print id, offset.
  538. * On all but the last stick a "+" in the flags portion.
  539. * For unfragmented datagrams, note the don't fragment flag.
  540. */
  541. ND_PRINT((ndo, ", id %u, offset %u, flags [%s], proto %s (%u)",
  542. EXTRACT_16BITS(&ipds->ip->ip_id),
  543. (ipds->off & 0x1fff) * 8,
  544. bittok2str(ip_frag_values, "none", ipds->off&0xe000),
  545. tok2str(ipproto_values,"unknown",ipds->ip->ip_p),
  546. ipds->ip->ip_p));
  547. ND_PRINT((ndo, ", length %u", EXTRACT_16BITS(&ipds->ip->ip_len)));
  548. if ((hlen - sizeof(struct ip)) > 0) {
  549. ND_PRINT((ndo, ", options ("));
  550. ip_optprint(ndo, (const u_char *)(ipds->ip + 1), hlen - sizeof(struct ip));
  551. ND_PRINT((ndo, ")"));
  552. }
  553. if (!ndo->ndo_Kflag && (const u_char *)ipds->ip + hlen <= ndo->ndo_snapend) {
  554. vec[0].ptr = (const uint8_t *)(const void *)ipds->ip;
  555. vec[0].len = hlen;
  556. sum = in_cksum(vec, 1);
  557. if (sum != 0) {
  558. ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum);
  559. ND_PRINT((ndo, ", bad cksum %x (->%x)!", ip_sum,
  560. in_cksum_shouldbe(ip_sum, sum)));
  561. }
  562. }
  563. ND_PRINT((ndo, ")\n "));
  564. }
  565. /*
  566. * If this is fragment zero, hand it to the next higher
  567. * level protocol.
  568. */
  569. if ((ipds->off & 0x1fff) == 0) {
  570. ipds->cp = (const u_char *)ipds->ip + hlen;
  571. ipds->nh = ipds->ip->ip_p;
  572. if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
  573. ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
  574. ND_PRINT((ndo, "%s > %s: ",
  575. ipaddr_string(ndo, &ipds->ip->ip_src),
  576. ipaddr_string(ndo, &ipds->ip->ip_dst)));
  577. }
  578. ip_print_demux(ndo, ipds);
  579. } else {
  580. /*
  581. * Ultra quiet now means that all this stuff should be
  582. * suppressed.
  583. */
  584. if (ndo->ndo_qflag > 1)
  585. return;
  586. /*
  587. * This isn't the first frag, so we're missing the
  588. * next level protocol header. print the ip addr
  589. * and the protocol.
  590. */
  591. ND_PRINT((ndo, "%s > %s:", ipaddr_string(ndo, &ipds->ip->ip_src),
  592. ipaddr_string(ndo, &ipds->ip->ip_dst)));
  593. if (!ndo->ndo_nflag && (p_name = netdb_protoname(ipds->ip->ip_p)) != NULL)
  594. ND_PRINT((ndo, " %s", p_name));
  595. else
  596. ND_PRINT((ndo, " ip-proto-%d", ipds->ip->ip_p));
  597. }
  598. return;
  599. trunc:
  600. ND_PRINT((ndo, "%s", tstr));
  601. return;
  602. }
  603. void
  604. ipN_print(netdissect_options *ndo, register const u_char *bp, register u_int length)
  605. {
  606. if (length < 1) {
  607. ND_PRINT((ndo, "truncated-ip %d", length));
  608. return;
  609. }
  610. ND_TCHECK(*bp);
  611. switch (*bp & 0xF0) {
  612. case 0x40:
  613. ip_print (ndo, bp, length);
  614. break;
  615. case 0x60:
  616. ip6_print (ndo, bp, length);
  617. break;
  618. default:
  619. ND_PRINT((ndo, "unknown ip %d", (*bp & 0xF0) >> 4));
  620. break;
  621. }
  622. return;
  623. trunc:
  624. ND_PRINT((ndo, "%s", tstr));
  625. return;
  626. }
  627. /*
  628. * Local Variables:
  629. * c-style: whitesmith
  630. * c-basic-offset: 8
  631. * End:
  632. */