nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* Copyright (c) 2001 NETLAB, Temple University |
2 | * Copyright (c) 2001 Protocol Engineering Lab, University of Delaware |
||
3 | * |
||
4 | * Jerry Heinz <gheinz@astro.temple.edu> |
||
5 | * John Fiore <jfiore@joda.cis.temple.edu> |
||
6 | * Armando L. Caro Jr. <acaro@cis.udel.edu> |
||
7 | * |
||
8 | * Redistribution and use in source and binary forms, with or without |
||
9 | * modification, are permitted provided that the following conditions |
||
10 | * are met: |
||
11 | * |
||
12 | * 1. Redistributions of source code must retain the above copyright |
||
13 | * notice, this list of conditions and the following disclaimer. |
||
14 | * |
||
15 | * 2. Redistributions in binary form must reproduce the above copyright |
||
16 | * notice, this list of conditions and the following disclaimer in the |
||
17 | * documentation and/or other materials provided with the distribution. |
||
18 | * |
||
19 | * 3. Neither the name of the University nor of the Laboratory may be used |
||
20 | * to endorse or promote products derived from this software without |
||
21 | * specific prior written permission. |
||
22 | * |
||
23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
33 | * SUCH DAMAGE. |
||
34 | */ |
||
35 | |||
36 | #define NETDISSECT_REWORKED |
||
37 | #ifdef HAVE_CONFIG_H |
||
38 | #include "config.h" |
||
39 | #endif |
||
40 | |||
41 | #include <tcpdump-stdinc.h> |
||
42 | |||
43 | #include "interface.h" |
||
44 | #include "addrtoname.h" |
||
45 | #include "extract.h" /* must come after interface.h */ |
||
46 | #include "ip.h" |
||
47 | #ifdef INET6 |
||
48 | #include "ip6.h" |
||
49 | #endif |
||
50 | |||
51 | /* Definitions from: |
||
52 | * |
||
53 | * SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola |
||
54 | * |
||
55 | * Redistribution and use in source and binary forms, with or without |
||
56 | * modification, are permitted provided that the following conditions |
||
57 | * are met: |
||
58 | * |
||
59 | * 1. Redistributions of source code must retain the above copyright |
||
60 | * notice, this list of conditions and the following disclaimer. |
||
61 | * |
||
62 | * 2. Redistributions in binary form must reproduce the above copyright |
||
63 | * notice, this list of conditions and the following disclaimer in the |
||
64 | * documentation and/or other materials provided with the distribution. |
||
65 | * |
||
66 | * 3. Neither the name of Cisco nor of Motorola may be used |
||
67 | * to endorse or promote products derived from this software without |
||
68 | * specific prior written permission. |
||
69 | * |
||
70 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
71 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
72 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
73 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
74 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
75 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
76 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
77 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
78 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
79 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
80 | * SUCH DAMAGE. |
||
81 | * |
||
82 | * This file is part of the SCTP reference Implementation |
||
83 | * |
||
84 | * |
||
85 | * Please send any bug reports or fixes you make to one of the following email |
||
86 | * addresses: |
||
87 | * |
||
88 | * rstewar1@email.mot.com |
||
89 | * kmorneau@cisco.com |
||
90 | * qxie1@email.mot.com |
||
91 | * |
||
92 | * Any bugs reported given to us we will try to fix... any fixes shared will |
||
93 | * be incorperated into the next SCTP release. |
||
94 | */ |
||
95 | |||
96 | /* The valid defines for all message |
||
97 | * types know to SCTP. 0 is reserved |
||
98 | */ |
||
99 | #define SCTP_DATA 0x00 |
||
100 | #define SCTP_INITIATION 0x01 |
||
101 | #define SCTP_INITIATION_ACK 0x02 |
||
102 | #define SCTP_SELECTIVE_ACK 0x03 |
||
103 | #define SCTP_HEARTBEAT_REQUEST 0x04 |
||
104 | #define SCTP_HEARTBEAT_ACK 0x05 |
||
105 | #define SCTP_ABORT_ASSOCIATION 0x06 |
||
106 | #define SCTP_SHUTDOWN 0x07 |
||
107 | #define SCTP_SHUTDOWN_ACK 0x08 |
||
108 | #define SCTP_OPERATION_ERR 0x09 |
||
109 | #define SCTP_COOKIE_ECHO 0x0a |
||
110 | #define SCTP_COOKIE_ACK 0x0b |
||
111 | #define SCTP_ECN_ECHO 0x0c |
||
112 | #define SCTP_ECN_CWR 0x0d |
||
113 | #define SCTP_SHUTDOWN_COMPLETE 0x0e |
||
114 | #define SCTP_FORWARD_CUM_TSN 0xc0 |
||
115 | #define SCTP_RELIABLE_CNTL 0xc1 |
||
116 | #define SCTP_RELIABLE_CNTL_ACK 0xc2 |
||
117 | |||
118 | static const struct tok sctp_chunkid_str[] = { |
||
119 | { SCTP_DATA, "DATA" }, |
||
120 | { SCTP_INITIATION, "INIT" }, |
||
121 | { SCTP_INITIATION_ACK, "INIT ACK" }, |
||
122 | { SCTP_SELECTIVE_ACK, "SACK" }, |
||
123 | { SCTP_HEARTBEAT_REQUEST, "HB REQ" }, |
||
124 | { SCTP_HEARTBEAT_ACK, "HB ACK" }, |
||
125 | { SCTP_ABORT_ASSOCIATION, "ABORT" }, |
||
126 | { SCTP_SHUTDOWN, "SHUTDOWN" }, |
||
127 | { SCTP_SHUTDOWN_ACK, "SHUTDOWN ACK" }, |
||
128 | { SCTP_OPERATION_ERR, "OP ERR" }, |
||
129 | { SCTP_COOKIE_ECHO, "COOKIE ECHO" }, |
||
130 | { SCTP_COOKIE_ACK, "COOKIE ACK" }, |
||
131 | { SCTP_ECN_ECHO, "ECN ECHO" }, |
||
132 | { SCTP_ECN_CWR, "ECN CWR" }, |
||
133 | { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" }, |
||
134 | { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, |
||
135 | { SCTP_RELIABLE_CNTL, "REL CTRL" }, |
||
136 | { SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" }, |
||
137 | { 0, NULL } |
||
138 | }; |
||
139 | |||
140 | /* Data Chuck Specific Flags */ |
||
141 | #define SCTP_DATA_FRAG_MASK 0x03 |
||
142 | #define SCTP_DATA_MIDDLE_FRAG 0x00 |
||
143 | #define SCTP_DATA_LAST_FRAG 0x01 |
||
144 | #define SCTP_DATA_FIRST_FRAG 0x02 |
||
145 | #define SCTP_DATA_NOT_FRAG 0x03 |
||
146 | #define SCTP_DATA_UNORDERED 0x04 |
||
147 | |||
148 | #define SCTP_ADDRMAX 60 |
||
149 | |||
150 | #define CHAN_HP 6704 |
||
151 | #define CHAN_MP 6705 |
||
152 | #define CHAN_LP 6706 |
||
153 | |||
154 | /* the sctp common header */ |
||
155 | |||
156 | struct sctpHeader{ |
||
157 | uint16_t source; |
||
158 | uint16_t destination; |
||
159 | uint32_t verificationTag; |
||
160 | uint32_t adler32; |
||
161 | }; |
||
162 | |||
163 | /* various descriptor parsers */ |
||
164 | |||
165 | struct sctpChunkDesc{ |
||
166 | uint8_t chunkID; |
||
167 | uint8_t chunkFlg; |
||
168 | uint16_t chunkLength; |
||
169 | }; |
||
170 | |||
171 | struct sctpParamDesc{ |
||
172 | uint16_t paramType; |
||
173 | uint16_t paramLength; |
||
174 | }; |
||
175 | |||
176 | |||
177 | struct sctpRelChunkDesc{ |
||
178 | struct sctpChunkDesc chk; |
||
179 | uint32_t serialNumber; |
||
180 | }; |
||
181 | |||
182 | struct sctpVendorSpecificParam { |
||
183 | struct sctpParamDesc p; /* type must be 0xfffe */ |
||
184 | uint32_t vendorId; /* vendor ID from RFC 1700 */ |
||
185 | uint16_t vendorSpecificType; |
||
186 | uint16_t vendorSpecificLen; |
||
187 | }; |
||
188 | |||
189 | |||
190 | /* Structures for the control parts */ |
||
191 | |||
192 | |||
193 | |||
194 | /* Sctp association init request/ack */ |
||
195 | |||
196 | /* this is used for init ack, too */ |
||
197 | struct sctpInitiation{ |
||
198 | uint32_t initTag; /* tag of mine */ |
||
199 | uint32_t rcvWindowCredit; /* rwnd */ |
||
200 | uint16_t NumPreopenStreams; /* OS */ |
||
201 | uint16_t MaxInboundStreams; /* MIS */ |
||
202 | uint32_t initialTSN; |
||
203 | /* optional param's follow in sctpParamDesc form */ |
||
204 | }; |
||
205 | |||
206 | struct sctpV4IpAddress{ |
||
207 | struct sctpParamDesc p; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */ |
||
208 | uint32_t ipAddress; |
||
209 | }; |
||
210 | |||
211 | |||
212 | struct sctpV6IpAddress{ |
||
213 | struct sctpParamDesc p; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */ |
||
214 | uint8_t ipAddress[16]; |
||
215 | }; |
||
216 | |||
217 | struct sctpDNSName{ |
||
218 | struct sctpParamDesc param; |
||
219 | uint8_t name[1]; |
||
220 | }; |
||
221 | |||
222 | |||
223 | struct sctpCookiePreserve{ |
||
224 | struct sctpParamDesc p; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */ |
||
225 | uint32_t extraTime; |
||
226 | }; |
||
227 | |||
228 | |||
229 | struct sctpTimeStamp{ |
||
230 | uint32_t ts_sec; |
||
231 | uint32_t ts_usec; |
||
232 | }; |
||
233 | |||
234 | /* wire structure of my cookie */ |
||
235 | struct cookieMessage{ |
||
236 | uint32_t TieTag_curTag; /* copied from assoc if present */ |
||
237 | uint32_t TieTag_hisTag; /* copied from assoc if present */ |
||
238 | int32_t cookieLife; /* life I will award this cookie */ |
||
239 | struct sctpTimeStamp timeEnteringState; /* the time I built cookie */ |
||
240 | struct sctpInitiation initAckISent; /* the INIT-ACK that I sent to my peer */ |
||
241 | uint32_t addressWhereISent[4]; /* I make this 4 ints so I get 128bits for future */ |
||
242 | int32_t addrtype; /* address type */ |
||
243 | uint16_t locScope; /* V6 local scope flag */ |
||
244 | uint16_t siteScope; /* V6 site scope flag */ |
||
245 | /* at the end is tacked on the INIT chunk sent in |
||
246 | * its entirety and of course our |
||
247 | * signature. |
||
248 | */ |
||
249 | }; |
||
250 | |||
251 | |||
252 | /* this guy is for use when |
||
253 | * I have a initiate message gloming the |
||
254 | * things together. |
||
255 | |||
256 | */ |
||
257 | struct sctpUnifiedInit{ |
||
258 | struct sctpChunkDesc uh; |
||
259 | struct sctpInitiation initm; |
||
260 | }; |
||
261 | |||
262 | struct sctpSendableInit{ |
||
263 | struct sctpHeader mh; |
||
264 | struct sctpUnifiedInit msg; |
||
265 | }; |
||
266 | |||
267 | |||
268 | /* Selective Acknowledgement |
||
269 | * has the following structure with |
||
270 | * a optional ammount of trailing int's |
||
271 | * on the last part (based on the numberOfDesc |
||
272 | * field). |
||
273 | */ |
||
274 | |||
275 | struct sctpSelectiveAck{ |
||
276 | uint32_t highestConseqTSN; |
||
277 | uint32_t updatedRwnd; |
||
278 | uint16_t numberOfdesc; |
||
279 | uint16_t numDupTsns; |
||
280 | }; |
||
281 | |||
282 | struct sctpSelectiveFrag{ |
||
283 | uint16_t fragmentStart; |
||
284 | uint16_t fragmentEnd; |
||
285 | }; |
||
286 | |||
287 | |||
288 | struct sctpUnifiedSack{ |
||
289 | struct sctpChunkDesc uh; |
||
290 | struct sctpSelectiveAck sack; |
||
291 | }; |
||
292 | |||
293 | /* for both RTT request/response the |
||
294 | * following is sent |
||
295 | */ |
||
296 | |||
297 | struct sctpHBrequest { |
||
298 | uint32_t time_value_1; |
||
299 | uint32_t time_value_2; |
||
300 | }; |
||
301 | |||
302 | /* here is what I read and respond with to. */ |
||
303 | struct sctpHBunified{ |
||
304 | struct sctpChunkDesc hdr; |
||
305 | struct sctpParamDesc hb; |
||
306 | }; |
||
307 | |||
308 | |||
309 | /* here is what I send */ |
||
310 | struct sctpHBsender{ |
||
311 | struct sctpChunkDesc hdr; |
||
312 | struct sctpParamDesc hb; |
||
313 | struct sctpHBrequest rtt; |
||
314 | int8_t addrFmt[SCTP_ADDRMAX]; |
||
315 | uint16_t userreq; |
||
316 | }; |
||
317 | |||
318 | |||
319 | |||
320 | /* for the abort and shutdown ACK |
||
321 | * we must carry the init tag in the common header. Just the |
||
322 | * common header is all that is needed with a chunk descriptor. |
||
323 | */ |
||
324 | struct sctpUnifiedAbort{ |
||
325 | struct sctpChunkDesc uh; |
||
326 | }; |
||
327 | |||
328 | struct sctpUnifiedAbortLight{ |
||
329 | struct sctpHeader mh; |
||
330 | struct sctpChunkDesc uh; |
||
331 | }; |
||
332 | |||
333 | struct sctpUnifiedAbortHeavy{ |
||
334 | struct sctpHeader mh; |
||
335 | struct sctpChunkDesc uh; |
||
336 | uint16_t causeCode; |
||
337 | uint16_t causeLen; |
||
338 | }; |
||
339 | |||
340 | /* For the graceful shutdown we must carry |
||
341 | * the tag (in common header) and the highest consequitive acking value |
||
342 | */ |
||
343 | struct sctpShutdown { |
||
344 | uint32_t TSN_Seen; |
||
345 | }; |
||
346 | |||
347 | struct sctpUnifiedShutdown{ |
||
348 | struct sctpChunkDesc uh; |
||
349 | struct sctpShutdown shut; |
||
350 | }; |
||
351 | |||
352 | /* in the unified message we add the trailing |
||
353 | * stream id since it is the only message |
||
354 | * that is defined as a operation error. |
||
355 | */ |
||
356 | struct sctpOpErrorCause{ |
||
357 | uint16_t cause; |
||
358 | uint16_t causeLen; |
||
359 | }; |
||
360 | |||
361 | struct sctpUnifiedOpError{ |
||
362 | struct sctpChunkDesc uh; |
||
363 | struct sctpOpErrorCause c; |
||
364 | }; |
||
365 | |||
366 | struct sctpUnifiedStreamError{ |
||
367 | struct sctpHeader mh; |
||
368 | struct sctpChunkDesc uh; |
||
369 | struct sctpOpErrorCause c; |
||
370 | uint16_t strmNum; |
||
371 | uint16_t reserved; |
||
372 | }; |
||
373 | |||
374 | struct staleCookieMsg{ |
||
375 | struct sctpHeader mh; |
||
376 | struct sctpChunkDesc uh; |
||
377 | struct sctpOpErrorCause c; |
||
378 | uint32_t moretime; |
||
379 | }; |
||
380 | |||
381 | /* the following is used in all sends |
||
382 | * where nothing is needed except the |
||
383 | * chunk/type i.e. shutdownAck Abort */ |
||
384 | |||
385 | struct sctpUnifiedSingleMsg{ |
||
386 | struct sctpHeader mh; |
||
387 | struct sctpChunkDesc uh; |
||
388 | }; |
||
389 | |||
390 | struct sctpDataPart{ |
||
391 | uint32_t TSN; |
||
392 | uint16_t streamId; |
||
393 | uint16_t sequence; |
||
394 | uint32_t payloadtype; |
||
395 | }; |
||
396 | |||
397 | struct sctpUnifiedDatagram{ |
||
398 | struct sctpChunkDesc uh; |
||
399 | struct sctpDataPart dp; |
||
400 | }; |
||
401 | |||
402 | struct sctpECN_echo{ |
||
403 | struct sctpChunkDesc uh; |
||
404 | uint32_t Lowest_TSN; |
||
405 | }; |
||
406 | |||
407 | |||
408 | struct sctpCWR{ |
||
409 | struct sctpChunkDesc uh; |
||
410 | uint32_t TSN_reduced_at; |
||
411 | }; |
||
412 | |||
413 | static const struct tok ForCES_channels[] = { |
||
414 | { CHAN_HP, "ForCES HP" }, |
||
415 | { CHAN_MP, "ForCES MP" }, |
||
416 | { CHAN_LP, "ForCES LP" }, |
||
417 | { 0, NULL } |
||
418 | }; |
||
419 | |||
420 | /* data chunk's payload protocol identifiers */ |
||
421 | |||
422 | #define SCTP_PPID_IUA 1 |
||
423 | #define SCTP_PPID_M2UA 2 |
||
424 | #define SCTP_PPID_M3UA 3 |
||
425 | #define SCTP_PPID_SUA 4 |
||
426 | #define SCTP_PPID_M2PA 5 |
||
427 | #define SCTP_PPID_V5UA 6 |
||
428 | #define SCTP_PPID_H248 7 |
||
429 | #define SCTP_PPID_BICC 8 |
||
430 | #define SCTP_PPID_TALI 9 |
||
431 | #define SCTP_PPID_DUA 10 |
||
432 | #define SCTP_PPID_ASAP 11 |
||
433 | #define SCTP_PPID_ENRP 12 |
||
434 | #define SCTP_PPID_H323 13 |
||
435 | #define SCTP_PPID_QIPC 14 |
||
436 | #define SCTP_PPID_SIMCO 15 |
||
437 | #define SCTP_PPID_DDPSC 16 |
||
438 | #define SCTP_PPID_DDPSSC 17 |
||
439 | #define SCTP_PPID_S1AP 18 |
||
440 | #define SCTP_PPID_RUA 19 |
||
441 | #define SCTP_PPID_HNBAP 20 |
||
442 | #define SCTP_PPID_FORCES_HP 21 |
||
443 | #define SCTP_PPID_FORCES_MP 22 |
||
444 | #define SCTP_PPID_FORCES_LP 23 |
||
445 | #define SCTP_PPID_SBC_AP 24 |
||
446 | #define SCTP_PPID_NBAP 25 |
||
447 | /* 26 */ |
||
448 | #define SCTP_PPID_X2AP 27 |
||
449 | |||
450 | static const struct tok PayloadProto_idents[] = { |
||
451 | { SCTP_PPID_IUA, "ISDN Q.921" }, |
||
452 | { SCTP_PPID_M2UA, "M2UA" }, |
||
453 | { SCTP_PPID_M3UA, "M3UA" }, |
||
454 | { SCTP_PPID_SUA, "SUA" }, |
||
455 | { SCTP_PPID_M2PA, "M2PA" }, |
||
456 | { SCTP_PPID_V5UA, "V5.2" }, |
||
457 | { SCTP_PPID_H248, "H.248" }, |
||
458 | { SCTP_PPID_BICC, "BICC" }, |
||
459 | { SCTP_PPID_TALI, "TALI" }, |
||
460 | { SCTP_PPID_DUA, "DUA" }, |
||
461 | { SCTP_PPID_ASAP, "ASAP" }, |
||
462 | { SCTP_PPID_ENRP, "ENRP" }, |
||
463 | { SCTP_PPID_H323, "H.323" }, |
||
464 | { SCTP_PPID_QIPC, "Q.IPC" }, |
||
465 | { SCTP_PPID_SIMCO, "SIMCO" }, |
||
466 | { SCTP_PPID_DDPSC, "DDPSC" }, |
||
467 | { SCTP_PPID_DDPSSC, "DDPSSC" }, |
||
468 | { SCTP_PPID_S1AP, "S1AP" }, |
||
469 | { SCTP_PPID_RUA, "RUA" }, |
||
470 | { SCTP_PPID_HNBAP, "HNBAP" }, |
||
471 | { SCTP_PPID_FORCES_HP, "ForCES HP" }, |
||
472 | { SCTP_PPID_FORCES_MP, "ForCES MP" }, |
||
473 | { SCTP_PPID_FORCES_LP, "ForCES LP" }, |
||
474 | { SCTP_PPID_SBC_AP, "SBc-AP" }, |
||
475 | { SCTP_PPID_NBAP, "NBAP" }, |
||
476 | /* 26 */ |
||
477 | { SCTP_PPID_X2AP, "X2AP" }, |
||
478 | { 0, NULL } |
||
479 | }; |
||
480 | |||
481 | |||
482 | static inline int isForCES_port(u_short Port) |
||
483 | { |
||
484 | if (Port == CHAN_HP) |
||
485 | return 1; |
||
486 | if (Port == CHAN_MP) |
||
487 | return 1; |
||
488 | if (Port == CHAN_LP) |
||
489 | return 1; |
||
490 | |||
491 | return 0; |
||
492 | } |
||
493 | |||
494 | void sctp_print(netdissect_options *ndo, |
||
495 | const u_char *bp, /* beginning of sctp packet */ |
||
496 | const u_char *bp2, /* beginning of enclosing */ |
||
497 | u_int sctpPacketLength) /* ip packet */ |
||
498 | { |
||
499 | const struct sctpHeader *sctpPktHdr; |
||
500 | const struct ip *ip; |
||
501 | #ifdef INET6 |
||
502 | const struct ip6_hdr *ip6; |
||
503 | #endif |
||
504 | const void *endPacketPtr; |
||
505 | u_short sourcePort, destPort; |
||
506 | int chunkCount; |
||
507 | const struct sctpChunkDesc *chunkDescPtr; |
||
508 | const void *nextChunk; |
||
509 | const char *sep; |
||
510 | int isforces = 0; |
||
511 | |||
512 | |||
513 | sctpPktHdr = (const struct sctpHeader*) bp; |
||
514 | endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength; |
||
515 | |||
516 | if( (u_long) endPacketPtr > (u_long) ndo->ndo_snapend) |
||
517 | endPacketPtr = (const void *) ndo->ndo_snapend; |
||
518 | ip = (struct ip *)bp2; |
||
519 | #ifdef INET6 |
||
520 | if (IP_V(ip) == 6) |
||
521 | ip6 = (const struct ip6_hdr *)bp2; |
||
522 | else |
||
523 | ip6 = NULL; |
||
524 | #endif /*INET6*/ |
||
525 | ND_TCHECK(*sctpPktHdr); |
||
526 | |||
527 | if (sctpPacketLength < sizeof(struct sctpHeader)) |
||
528 | { |
||
529 | ND_PRINT((ndo, "truncated-sctp - %ld bytes missing!", |
||
530 | (long)sctpPacketLength-sizeof(struct sctpHeader))); |
||
531 | return; |
||
532 | } |
||
533 | |||
534 | /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */ |
||
535 | /* is now only as long as the payload */ |
||
536 | |||
537 | sourcePort = EXTRACT_16BITS(&sctpPktHdr->source); |
||
538 | destPort = EXTRACT_16BITS(&sctpPktHdr->destination); |
||
539 | |||
540 | #ifdef INET6 |
||
541 | if (ip6) { |
||
542 | ND_PRINT((ndo, "%s.%d > %s.%d: sctp", |
||
543 | ip6addr_string(ndo, &ip6->ip6_src), |
||
544 | sourcePort, |
||
545 | ip6addr_string(ndo, &ip6->ip6_dst), |
||
546 | destPort)); |
||
547 | } else |
||
548 | #endif /*INET6*/ |
||
549 | { |
||
550 | ND_PRINT((ndo, "%s.%d > %s.%d: sctp", |
||
551 | ipaddr_string(ndo, &ip->ip_src), |
||
552 | sourcePort, |
||
553 | ipaddr_string(ndo, &ip->ip_dst), |
||
554 | destPort)); |
||
555 | } |
||
556 | |||
557 | if (isForCES_port(sourcePort)) { |
||
558 | ND_PRINT((ndo, "[%s]", tok2str(ForCES_channels, NULL, sourcePort))); |
||
559 | isforces = 1; |
||
560 | } |
||
561 | if (isForCES_port(destPort)) { |
||
562 | ND_PRINT((ndo, "[%s]", tok2str(ForCES_channels, NULL, destPort))); |
||
563 | isforces = 1; |
||
564 | } |
||
565 | |||
566 | if (ndo->ndo_vflag >= 2) |
||
567 | sep = "\n\t"; |
||
568 | else |
||
569 | sep = " ("; |
||
570 | /* cycle through all chunks, printing information on each one */ |
||
571 | for (chunkCount = 0, |
||
572 | chunkDescPtr = (const struct sctpChunkDesc *) |
||
573 | ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader)); |
||
574 | chunkDescPtr != NULL && |
||
575 | ( (const void *) |
||
576 | ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc)) |
||
577 | <= endPacketPtr); |
||
578 | |||
579 | chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++) |
||
580 | { |
||
581 | uint16_t chunkLength; |
||
582 | const u_char *chunkEnd; |
||
583 | uint16_t align; |
||
584 | |||
585 | ND_TCHECK(*chunkDescPtr); |
||
586 | chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength); |
||
587 | if (chunkLength < sizeof(*chunkDescPtr)) { |
||
588 | ND_PRINT((ndo, "%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength)); |
||
589 | break; |
||
590 | } |
||
591 | |||
592 | ND_TCHECK2(*((uint8_t *)chunkDescPtr), chunkLength); |
||
593 | chunkEnd = ((const u_char*)chunkDescPtr + chunkLength); |
||
594 | |||
595 | align=chunkLength % 4; |
||
596 | if (align != 0) |
||
597 | align = 4 - align; |
||
598 | |||
599 | nextChunk = (const void *) (chunkEnd + align); |
||
600 | |||
601 | ND_PRINT((ndo, "%s%d) ", sep, chunkCount+1)); |
||
602 | ND_PRINT((ndo, "[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x", |
||
603 | chunkDescPtr->chunkID))); |
||
604 | switch (chunkDescPtr->chunkID) |
||
605 | { |
||
606 | case SCTP_DATA : |
||
607 | { |
||
608 | const struct sctpDataPart *dataHdrPtr; |
||
609 | uint32_t ppid; |
||
610 | const u_char *payloadPtr; |
||
611 | u_int payload_size; |
||
612 | |||
613 | if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) |
||
614 | == SCTP_DATA_UNORDERED) |
||
615 | ND_PRINT((ndo, "(U)")); |
||
616 | |||
617 | if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) |
||
618 | == SCTP_DATA_FIRST_FRAG) |
||
619 | ND_PRINT((ndo, "(B)")); |
||
620 | |||
621 | if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) |
||
622 | == SCTP_DATA_LAST_FRAG) |
||
623 | ND_PRINT((ndo, "(E)")); |
||
624 | |||
625 | if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) |
||
626 | == SCTP_DATA_UNORDERED) |
||
627 | || |
||
628 | ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) |
||
629 | == SCTP_DATA_FIRST_FRAG) |
||
630 | || |
||
631 | ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) |
||
632 | == SCTP_DATA_LAST_FRAG) ) |
||
633 | ND_PRINT((ndo, " ")); |
||
634 | |||
635 | dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1); |
||
636 | |||
637 | ppid = EXTRACT_32BITS(&dataHdrPtr->payloadtype); |
||
638 | ND_PRINT((ndo, "[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN))); |
||
639 | ND_PRINT((ndo, "[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId))); |
||
640 | ND_PRINT((ndo, "[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence))); |
||
641 | ND_PRINT((ndo, "[PPID %s] ", |
||
642 | tok2str(PayloadProto_idents, "0x%x", ppid))); |
||
643 | |||
644 | if (!isforces) { |
||
645 | isforces = (ppid == SCTP_PPID_FORCES_HP) || |
||
646 | (ppid == SCTP_PPID_FORCES_MP) || |
||
647 | (ppid == SCTP_PPID_FORCES_LP); |
||
648 | } |
||
649 | |||
650 | payloadPtr = (const u_char *) (dataHdrPtr + 1); |
||
651 | if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) < |
||
652 | sizeof(struct sctpDataPart) + sizeof(struct sctpChunkDesc) + 1) { |
||
653 | ND_PRINT((ndo, "bogus chunk length %u]", EXTRACT_16BITS(&chunkDescPtr->chunkLength))); |
||
654 | return; |
||
655 | } |
||
656 | |||
657 | payload_size = EXTRACT_16BITS(&chunkDescPtr->chunkLength) - |
||
658 | (sizeof(struct sctpDataPart) + sizeof(struct sctpChunkDesc)); |
||
659 | |||
660 | if (isforces) { |
||
661 | forces_print(ndo, payloadPtr, payload_size); |
||
662 | } else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */ |
||
663 | /* at the command line */ |
||
664 | switch (ppid) { |
||
665 | case SCTP_PPID_M3UA : |
||
666 | m3ua_print(ndo, payloadPtr, payload_size); |
||
667 | break; |
||
668 | default: |
||
669 | ND_PRINT((ndo, "[Payload")); |
||
670 | if (!ndo->ndo_suppress_default_print) { |
||
671 | ND_PRINT((ndo, ":")); |
||
672 | ND_DEFAULTPRINT(payloadPtr, payload_size); |
||
673 | } |
||
674 | ND_PRINT((ndo, "]")); |
||
675 | break; |
||
676 | } |
||
677 | } |
||
678 | break; |
||
679 | } |
||
680 | case SCTP_INITIATION : |
||
681 | { |
||
682 | const struct sctpInitiation *init; |
||
683 | |||
684 | init=(const struct sctpInitiation*)(chunkDescPtr+1); |
||
685 | ND_PRINT((ndo, "[init tag: %u] ", EXTRACT_32BITS(&init->initTag))); |
||
686 | ND_PRINT((ndo, "[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit))); |
||
687 | ND_PRINT((ndo, "[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams))); |
||
688 | ND_PRINT((ndo, "[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams))); |
||
689 | ND_PRINT((ndo, "[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN))); |
||
690 | |||
691 | #if(0) /* ALC you can add code for optional params here */ |
||
692 | if( (init+1) < chunkEnd ) |
||
693 | ND_PRINT((ndo, " @@@@@ UNFINISHED @@@@@@%s\n", |
||
694 | "Optional params present, but not printed.")); |
||
695 | #endif |
||
696 | break; |
||
697 | } |
||
698 | case SCTP_INITIATION_ACK : |
||
699 | { |
||
700 | const struct sctpInitiation *init; |
||
701 | |||
702 | init=(const struct sctpInitiation*)(chunkDescPtr+1); |
||
703 | ND_PRINT((ndo, "[init tag: %u] ", EXTRACT_32BITS(&init->initTag))); |
||
704 | ND_PRINT((ndo, "[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit))); |
||
705 | ND_PRINT((ndo, "[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams))); |
||
706 | ND_PRINT((ndo, "[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams))); |
||
707 | ND_PRINT((ndo, "[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN))); |
||
708 | |||
709 | #if(0) /* ALC you can add code for optional params here */ |
||
710 | if( (init+1) < chunkEnd ) |
||
711 | ND_PRINT((ndo, " @@@@@ UNFINISHED @@@@@@%s\n", |
||
712 | "Optional params present, but not printed.")); |
||
713 | #endif |
||
714 | break; |
||
715 | } |
||
716 | case SCTP_SELECTIVE_ACK: |
||
717 | { |
||
718 | const struct sctpSelectiveAck *sack; |
||
719 | const struct sctpSelectiveFrag *frag; |
||
720 | int fragNo, tsnNo; |
||
721 | const u_char *dupTSN; |
||
722 | |||
723 | sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1); |
||
724 | ND_PRINT((ndo, "[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN))); |
||
725 | ND_PRINT((ndo, "[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd))); |
||
726 | ND_PRINT((ndo, "[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc))); |
||
727 | ND_PRINT((ndo, "[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns))); |
||
728 | |||
729 | |||
730 | /* print gaps */ |
||
731 | for (frag = ( (const struct sctpSelectiveFrag *) |
||
732 | ((const struct sctpSelectiveAck *) sack+1)), |
||
733 | fragNo=0; |
||
734 | (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc); |
||
735 | frag++, fragNo++) |
||
736 | ND_PRINT((ndo, "\n\t\t[gap ack block #%d: start = %u, end = %u] ", |
||
737 | fragNo+1, |
||
738 | EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart), |
||
739 | EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd))); |
||
740 | |||
741 | |||
742 | /* print duplicate TSNs */ |
||
743 | for (dupTSN = (const u_char *)frag, tsnNo=0; |
||
744 | (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns); |
||
745 | dupTSN += 4, tsnNo++) |
||
746 | ND_PRINT((ndo, "\n\t\t[dup TSN #%u: %u] ", tsnNo+1, |
||
747 | EXTRACT_32BITS(dupTSN))); |
||
748 | |||
749 | break; |
||
750 | } |
||
751 | } |
||
752 | |||
753 | if (ndo->ndo_vflag < 2) |
||
754 | sep = ", ("; |
||
755 | } |
||
756 | return; |
||
757 | |||
758 | trunc: |
||
759 | ND_PRINT((ndo, "[|sctp]")); |
||
760 | } |