Print this page
dccp: getting kernel segfaults, back out recent added features
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/inet/dccp/dccp_output.c
+++ new/usr/src/uts/common/inet/dccp/dccp_output.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Copyright 2012 David Hoeppner. All rights reserved.
29 29 */
30 30
31 31 /*
32 32 * Functions related to the output path.
33 33 */
34 34
35 35 #include <sys/types.h>
36 36 #include <sys/stream.h>
37 37 #include <sys/strsun.h>
38 38 #include <sys/strsubr.h>
39 39 #include <sys/stropts.h>
40 40 #include <sys/strlog.h>
41 41 #define _SUN_TPI_VERSION 2
42 42 #include <sys/tihdr.h>
43 43 #include <sys/suntpi.h>
44 44 #include <sys/xti_inet.h>
45 45 #include <sys/squeue_impl.h>
46 46 #include <sys/squeue.h>
47 47 #include <sys/tsol/tnet.h>
48 48
49 49 #include <inet/common.h>
50 50 #include <inet/dccp_impl.h>
51 51 #include <inet/dccp_stack.h>
52 52 #include <inet/ip.h>
53 53 #include <inet/ipsec_impl.h>
54 54
55 55 #include <sys/cmn_err.h>
56 56
57 57 static void dccp_xmit_early_reset(char *, mblk_t *, uint32_t, uint32_t,
58 58 int, ip_recv_attr_t *, ip_stack_t *, conn_t *);
59 59 static boolean_t dccp_send_rst_chk(dccp_stack_t *);
60 60
61 61 /*
62 62 * STREAMS
63 63 */
64 64 void
65 65 dccp_wput(queue_t *q, mblk_t *mp)
66 66 {
67 67 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput");
68 68 }
69 69
70 70 /*
71 71 * Fast path write put.
72 72 */
73 73 void
74 74 dccp_wput_data(dccp_t *dccp, mblk_t *mp, boolean_t urgent)
75 75 {
76 76 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput_data");
77 77 }
78 78
↓ open down ↓ |
78 lines elided |
↑ open up ↑ |
79 79 /*
80 80 *
81 81 */
82 82 void
83 83 dccp_wput_sock(queue_t *wq, mblk_t *mp)
84 84 {
85 85 conn_t *connp = Q_TO_CONN(wq);
86 86 dccp_t *dccp = connp->conn_dccp;
87 87 struct T_capability_req *car = (struct T_capability_req *)mp->b_rptr;
88 88
89 + cmn_err(CE_NOTE, "dccp_wput_sock");
90 +
89 91 ASSERT(wq->q_qinfo == &dccp_sock_winit);
90 92 wq->q_qinfo = &dccp_winit;
91 93
92 94 ASSERT(IPCL_IS_TCP(connp));
93 95 ASSERT(DCCP_IS_SOCKET(dccp));
94 96
95 97 if (DB_TYPE(mp) == M_PCPROTO &&
96 98 MBLKL(mp) == sizeof (struct T_capability_req) &&
97 99 car->PRIM_type == T_CAPABILITY_REQ) {
98 100 dccp_capability_req(dccp, mp);
99 101 return;
100 102 }
101 103
102 104 dccp_wput(wq, mp);
103 105 }
104 106
105 107 /* ARGSUSED */
106 108 void
107 109 dccp_wput_fallback(queue_t *eq, mblk_t *mp)
108 110 {
109 111 cmn_err(CE_NOTE, "dccp_output.c: dccp_wput_fallback");
110 112
111 113 #ifdef DEBUG
112 114 cmn_err(CE_CONT, "tcp_wput_fallback: Message during fallback \n");
113 115 #endif /* DEBUG */
114 116
115 117 freemsg(mp);
116 118 }
117 119
118 120 /*
119 121 * Output fast path.
120 122 */
121 123 void
122 124 dccp_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
123 125 {
124 126 conn_t *connp = (conn_t *)arg;
125 127 dccp_t *dccp = connp->conn_dccp;
126 128 dccp_stack_t *dccps = dccp->dccp_dccps;
127 129 dccpha_t *dccpha;
128 130 mblk_t *mp1;
129 131 ip_xmit_attr_t *ixa;
130 132 struct datab *db;
131 133 uchar_t *rptr;
132 134 uint32_t msize;
133 135 uint32_t sum;
134 136 int len;
135 137 int plen;
136 138
137 139 cmn_err(CE_NOTE, "dccp_output.c: dccp_output");
138 140
139 141 ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
140 142 (connp->conn_fanout == NULL && connp->conn_ref >= 3));
141 143
142 144 ASSERT(DB_TYPE(mp) == M_DATA);
143 145 msize = (mp->b_cont == NULL) ? MBLKL(mp) : msgdsize(mp);
144 146
145 147 ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
146 148 len = (int)(mp->b_wptr - mp->b_rptr);
147 149
148 150 if ((mp->b_cont != NULL) ||
149 151 (dccp->dccp_state != DCCPS_OPEN) ||
150 152 (len == 0)) {
151 153 dccp_wput_data(dccp, mp, B_FALSE);
152 154 return;
153 155 }
154 156
155 157 mp1 = dupb(mp);
156 158 if (mp1 == NULL) {
157 159 goto no_memory;
158 160 }
159 161
160 162 /* Adjust header information */
161 163 dccpha = dccp->dccp_dccpha;
162 164
163 165 sum = len + connp->conn_ht_ulp_len + connp->conn_sum;
164 166 sum = (sum >> 16) + (sum & 0xffff);
165 167 dccpha->dha_sum = htons(sum);
166 168
167 169 DCCPS_BUMP_MIB(dccps, dccpOutDataSegs);
168 170 DCCPS_UPDATE_MIB(dccps, dccpOutDataBytes, len);
169 171 BUMP_LOCAL(dccp->dccp_obsegs);
170 172
171 173 plen = len + connp->conn_ht_iphc_len;
172 174
173 175 ixa = connp->conn_ixa;
174 176 ixa->ixa_pktlen = plen;
175 177
176 178 if (ixa->ixa_flags & IXAF_IS_IPV4) {
177 179 dccp->dccp_ipha->ipha_length = htons(plen);
178 180 } else {
179 181 dccp->dccp_ip6h->ip6_plen = htons(plen - IPV6_HDR_LEN);
180 182 }
181 183
182 184 rptr = mp1->b_rptr;
183 185 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
184 186
185 187 dccp_send_data(dccp, mp1);
186 188
187 189 return;
188 190
189 191 no_memory:
190 192 return;
191 193 }
192 194
193 195 void
194 196 dccp_output_urgent(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
195 197 {
196 198 cmn_err(CE_NOTE, "dccp_output.c: dccp_output_urgent");
197 199 }
198 200
199 201 void
200 202 dccp_close_output(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
201 203 {
202 204 conn_t *connp = (conn_t *)arg;
203 205 dccp_t *dccp = connp->conn_dccp;
204 206 dccp_stack_t *dccps = dccp->dccp_dccps;
205 207 char *msg;
206 208
207 209 cmn_err(CE_NOTE, "dccp_output.c: dccp_close_output");
208 210
209 211 /*
210 212 * When a non-STREAMS socket is being closed, it does not always
211 213 * stick around waiting for tcp_close_output to run and can therefore
212 214 * have dropped a reference already. So adjust the asserts accordingly.
213 215 */
214 216 ASSERT((connp->conn_fanout != NULL &&
215 217 connp->conn_ref >= (IPCL_IS_NONSTR(connp) ? 3 : 4)) ||
216 218 (connp->conn_fanout == NULL &&
217 219 connp->conn_ref >= (IPCL_IS_NONSTR(connp) ? 2 : 3)));
218 220
219 221 msg = NULL;
220 222 switch (dccp->dccp_state) {
221 223 case DCCPS_CLOSED:
222 224 break;
223 225 case DCCPS_BOUND:
224 226 break;
225 227 case DCCPS_REQUEST:
226 228 msg = "dccp_close, during connect";
227 229 break;
228 230 case DCCPS_RESPOND:
229 231 /* FALLTHRU */
230 232 default:
231 233 /*
232 234 * If SO_LINGER has set a zero linger time, abort the
233 235 * connection with a reset.
234 236 */
235 237 if (connp->conn_linger && connp->conn_lingertime == 0) {
236 238 msg = "dccp_close, zero lingertime";
237 239 break;
238 240 }
239 241 }
240 242 }
241 243
242 244 #pragma inline(dccp_send_data)
243 245
244 246 void
245 247 dccp_send_data(dccp_t *dccp, mblk_t *mp)
246 248 {
247 249 conn_t *connp = dccp->dccp_connp;
248 250 int error;
249 251
250 252 cmn_err(CE_NOTE, "dccp_output.c: dccp_sent_data");
251 253
252 254 /* XXX zcopy aware */
253 255
254 256 DTRACE_DCCP5(send, mblk_t *, NULL, ip_xmit_attr_t *, connp->conn_ixa,
255 257 __dtrace_dccp_void_ip_t *, mp->b_rptr, dccp_t *, dccp,
256 258 __dtrace_dccp_dccph_t *,
257 259 &mp->b_rptr[connp->conn_ixa->ixa_ip_hdr_length]);
258 260
259 261 ASSERT(connp->conn_ixa->ixa_notify_cookie == connp->conn_tcp);
260 262 error = conn_ip_output(mp, connp->conn_ixa);
261 263 if (error != 0) {
262 264 cmn_err(CE_NOTE, "conn_ip_output failed with code %d\n", error);
263 265 }
264 266 }
265 267
266 268 /*
267 269 * Send a reset as response to an incoming packet or
268 270 * reset a connection.
269 271 */
270 272 void
271 273 dccp_xmit_listeners_reset(mblk_t *mp, ip_recv_attr_t *ira, ip_stack_t *ipst,
272 274 conn_t *connp)
273 275 {
274 276 netstack_t *ns = ipst->ips_netstack;
275 277 dccp_stack_t *dccps = ns->netstack_dccp;
276 278 ipsec_stack_t *ipss = dccps->dccps_netstack->netstack_ipsec;
277 279 dccpha_t *dccpha;
278 280 ipha_t *ipha;
279 281 ip6_t *ip6h;
280 282 uchar_t *rptr;
281 283 uint32_t seq_len;
282 284 uint_t ip_hdr_len = ira->ira_ip_hdr_length;
283 285 boolean_t policy_present;
284 286
285 287 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_listeners_reset");
286 288
287 289 DCCP_STAT(dccps, dccp_no_listener);
288 290
289 291 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
290 292 policy_present = ipss->ipsec_inbound_v4_policy_present;
291 293 ipha = (ipha_t *)mp->b_rptr;
292 294 ip6h = NULL;
293 295 } else {
294 296 policy_present = ipss->ipsec_inbound_v6_policy_present;
295 297 ipha = NULL;
296 298 ip6h = (ip6_t *)mp->b_rptr;
297 299 }
298 300
299 301 if (policy_present) {
300 302 mp = ipsec_check_global_policy(mp, (conn_t *)NULL, ipha, ip6h,
301 303 ira, ns);
302 304 if (mp == NULL) {
303 305 return;
304 306 }
305 307 }
306 308
307 309 rptr = mp->b_rptr;
308 310
309 311 dccpha = (dccpha_t *)&rptr[ip_hdr_len];
310 312
311 313 seq_len = msgdsize(mp) - (ip_hdr_len);
312 314
313 315 dccp_xmit_early_reset("no dccp, reset", mp, 0,
314 316 0, 0, ira, ipst, connp);
315 317 }
316 318
317 319 /*
318 320 * RFC 4340, Section 8.1.3
319 321 */
320 322 static void
321 323 dccp_xmit_early_reset(char *str, mblk_t *mp, uint32_t seq, uint32_t ack, int ctl,
322 324 ip_recv_attr_t *ira, ip_stack_t *ipst, conn_t *connp)
323 325 {
324 326 dccpha_t *dccpha;
325 327 dccpha_t *nmp_dccpha;
326 328 dccpha_ack_t *nmp_dccpha_ack;
327 329 dccpha_reset_t *dccpha_reset;
328 330 dccpha_reset_t *nmp_dccpha_reset;
329 331 dccpha_ext_t *dccpha_ext;
330 332 dccpha_ext_t *nmp_dccpha_ext;
331 333 netstack_t *ns = ipst->ips_netstack;
332 334 dccp_stack_t *dccps = ns->netstack_dccp;
333 335 ip6_t *ip6h;
334 336 ipha_t *ipha;
335 337 ipha_t *nmp_ipha;
336 338 ip_xmit_attr_t ixas;
337 339 ip_xmit_attr_t *ixa;
338 340 in6_addr_t v6addr;
339 341 ipaddr_t v4addr;
340 342 mblk_t *nmp;
341 343 uint64_t pkt_ack;
342 344 uint_t ip_hdr_len = ira->ira_ip_hdr_length;
343 345 ushort_t port;
344 346 ushort_t len;
345 347
346 348 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_early_reset");
347 349
348 350 if (!dccp_send_rst_chk(dccps)) {
349 351 cmn_err(CE_NOTE, "dccp_output.c: not sending reset packet");
350 352 DCCP_STAT(dccps, dccp_rst_unsent);
351 353 freemsg(mp);
352 354 return;
353 355 }
354 356
355 357 bzero(&ixas, sizeof (ixas));
356 358 ixa = &ixas;
357 359
358 360 ixa->ixa_flags |= IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE;
359 361 ixa->ixa_protocol = IPPROTO_DCCP;
360 362 ixa->ixa_zoneid = ira->ira_zoneid;
361 363 ixa->ixa_ifindex = 0;
362 364 ixa->ixa_ipst = ipst;
363 365 ixa->ixa_cred = kcred;
364 366 ixa->ixa_cpid = NOPID;
365 367
366 368 if (str && dccps->dccps_dbg) {
367 369 (void) strlog(DCCP_MOD_ID, 0, 1, SL_TRACE,
368 370 "dccp_xmit_early_reset: '%s', seq 0x%x, ack 0x%x, "
369 371 "flags 0x%x",
370 372 str, seq, ack, ctl);
371 373 }
372 374
373 375 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
374 376 ipha = (ipha_t *)mp->b_rptr;
375 377
376 378 } else {
377 379 /* XXX */
378 380 }
379 381
380 382 /*
381 383 * Allocate a new DCCP reset message
382 384 */
383 385 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t);
384 386 nmp = allocb(len, BPRI_MED);
385 387 if (nmp == NULL) {
386 388 cmn_err(CE_NOTE, "alloc failed");
387 389 return;
388 390 }
389 391 bcopy(mp->b_rptr, nmp->b_wptr, ip_hdr_len + sizeof (dccpha_t));
390 392
391 393 nmp_dccpha = (dccpha_t *)&nmp->b_rptr[ip_hdr_len];
392 394 nmp_dccpha->dha_offset = 7;
393 395
394 396 if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
395 397 nmp_ipha = (ipha_t *)nmp->b_rptr;
396 398
397 399 nmp_ipha->ipha_length = htons(len);
398 400 nmp_ipha->ipha_src = ipha->ipha_dst;
399 401 nmp_ipha->ipha_dst = ipha->ipha_src;
400 402
401 403 ixa->ixa_flags |= IXAF_IS_IPV4;
402 404 ixa->ixa_ip_hdr_length = ip_hdr_len;
403 405 } else {
404 406 cmn_err(CE_NOTE, "not v4");
405 407 }
406 408
407 409 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
408 410
409 411 nmp->b_wptr = &nmp->b_rptr[len];
410 412
411 413 ixa->ixa_pktlen = len; // ?
412 414
413 415 nmp_dccpha->dha_fport = dccpha->dha_lport;
414 416 nmp_dccpha->dha_lport = dccpha->dha_fport;
415 417 nmp_dccpha->dha_type = DCCP_PKT_RESET;
416 418 nmp_dccpha->dha_x = 1;
417 419 nmp_dccpha->dha_res_seq = 0;
418 420 nmp_dccpha->dha_seq = 0;
419 421
420 422 nmp_dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t));
421 423
422 424 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
423 425 nmp_dccpha_ext = (dccpha_ext_t *)&nmp->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
424 426 nmp_dccpha_ext->dha_ext_seq = 0;
425 427
426 428 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t);
427 429 nmp_dccpha_ack = (dccpha_ack_t *)&nmp->b_rptr[len];
428 430 nmp_dccpha_ack->dha_ack_high = dccpha->dha_seq;
429 431 nmp_dccpha_ack->dha_ack_low = dccpha_ext->dha_ext_seq;
430 432
431 433 len = ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t);
432 434 nmp_dccpha_reset = (dccpha_reset_t *)&nmp->b_rptr[len];
433 435 nmp_dccpha_reset->dha_reset_code = DCCP_RESET_CONNECTION_REFUSED;
434 436 nmp_dccpha_reset->dha_reset_data[0] = 0;
435 437 nmp_dccpha_reset->dha_reset_data[1] = 0;
436 438 nmp_dccpha_reset->dha_reset_data[2] = 0;
437 439
438 440 (void) ip_output_simple(nmp, ixa);
439 441
440 442 ixa_cleanup(ixa);
441 443 }
442 444
443 445 /*
444 446 *
445 447 */
446 448 static boolean_t
447 449 dccp_send_rst_chk(dccp_stack_t *dccps)
448 450 {
449 451 int64_t now;
450 452
451 453 if (dccps->dccps_rst_sent_rate_enabled != 0) {
452 454 now = ddi_get_lbolt64();
453 455 if (TICK_TO_MSEC(now - dccps->dccps_last_rst_intrvl) >
454 456 1 * SECONDS) {
455 457 dccps->dccps_last_rst_intrvl = now;
456 458 dccps->dccps_rst_cnt = 1;
457 459 } else if (++dccps->dccps_rst_cnt > dccps->dccps_rst_sent_rate) {
458 460 return (B_FALSE);
459 461 }
460 462 }
461 463
462 464 return (B_TRUE);
463 465 }
464 466
465 467 /* ARGSUSED2 */
466 468 void
467 469 dccp_send_synack(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *dummy)
468 470 {
469 471 conn_t *econnp = (conn_t *)arg;
470 472 dccp_t *dccp = econnp->conn_dccp;
471 473 ip_xmit_attr_t *ixa = econnp->conn_ixa;
472 474
473 475 cmn_err(CE_NOTE, "dccp_output.c: dccp_send_synack");
474 476
475 477 /*
476 478 * Guard against a RESET having blown it away while on the
477 479 * squeue.
478 480 */
479 481 if (dccp->dccp_state == DCCPS_CLOSED) {
480 482 freemsg(mp);
481 483 return;
482 484 }
483 485
484 486 ixa->ixa_pktlen = msgdsize(mp);
485 487 (void) conn_ip_output(mp, ixa);
486 488 }
487 489
488 490 mblk_t *
489 491 dccp_xmit_mp(dccp_t *dccp, mblk_t *mp, int32_t max_to_send, int32_t *offset,
490 492 mblk_t **end_mp, uint32_t seq, boolean_t sendall, uint32_t *seg_len,
491 493 boolean_t rexmit)
492 494 {
493 495 conn_t *connp = dccp->dccp_connp;
494 496 dccp_stack_t *dccps = dccp->dccp_dccps;
495 497 dccpha_t *dccpha;
496 498 dccpha_ext_t *dccpha_ext;
497 499 dccpha_ack_t *dccpha_ack;
498 500 dccpha_srv_t *dccpha_srv;
499 501 ip_xmit_attr_t *ixa = connp->conn_ixa;
500 502 mblk_t *mp1;
501 503 uchar_t *rptr;
502 504 ushort_t len;
503 505 int data_length;
504 506
505 507 cmn_err(CE_NOTE, "dccp_output.c: dccp_xmit_mp");
506 508
507 509 // dccpha_t already in iphc_len?
508 510 len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4;
509 511
510 512 mp1 = allocb(len, BPRI_MED);
511 513 if (mp1 == NULL) {
512 514 cmn_err(CE_NOTE, "allocb failed");
513 515 return (NULL);
514 516 }
515 517
516 518 data_length = 0;
517 519
518 520 rptr = mp1->b_rptr;
519 521 mp1->b_wptr = &mp1->b_rptr[len];
520 522 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
521 523 dccpha = (dccpha_t *)&rptr[ixa->ixa_ip_hdr_length];
522 524 dccpha->dha_type = DCCP_PKT_RESPONSE;
523 525 dccpha->dha_offset = 8;
524 526 dccpha->dha_x = 1;
525 527 dccpha->dha_ccval = 0;
526 528 dccpha->dha_cscov = 0;
527 529 dccpha->dha_reserved = 0;
528 530 dccpha->dha_res_seq = 0;
529 531 dccpha->dha_seq = 0;
530 532
531 533 dccpha_ext = (dccpha_ext_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t)];
532 534 dccpha_ext->dha_ext_seq = 0;
533 535
534 536 dccpha_ack = (dccpha_ack_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t) + sizeof (dccpha_ext_t)];
535 537 dccpha_ack->dha_ack_reserved = 0;
536 538 dccpha_ack->dha_ack_high = 0;
537 539 dccpha_ack->dha_ack_low = 0;
538 540
539 541 dccpha_srv = (dccpha_srv_t *)&rptr[ixa->ixa_ip_hdr_length + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t)];
540 542 dccpha_srv->dha_srv_code = 0;
541 543
542 544 return (mp1);
543 545 }
544 546
545 547 /*
546 548 * Generate a DCCP-Response packet.
547 549 */
548 550 mblk_t *
549 551 dccp_generate_response(conn_t *connp, mblk_t *mp)
550 552 {
551 553 dccpha_t *dccpha;
552 554 dccpha_ext_t *dccpha_ext;
553 555 dccpha_ack_t *dccpha_ack;
554 556 dccpha_srv_t *dccpha_srv;
555 557 mblk_t *mp1;
556 558 uint64_t seq;
557 559 uint64_t ack;
558 560 uint16_t ack_high;
559 561 uint32_t ack_low;
560 562 // uint_t ip_hdr_len = ira->ira_ip_hdr_length;
561 563 ip_xmit_attr_t *ixa = connp->conn_ixa;
562 564 uint_t ip_hdr_len;
563 565 uint_t len;
564 566 uint_t total_hdr_len;
565 567 uchar_t *rptr;
566 568 dccp_t *dccp = connp->conn_dccp;
567 569 void *options;
568 570 size_t opt_len;
569 571 int error;
570 572
571 573 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_packet");
572 574
573 575 ip_hdr_len = ixa->ixa_ip_hdr_length;
574 576
575 577 if (mp == NULL) {
576 578 cmn_err(CE_NOTE, "NULL pointer mp");
577 579 return (NULL);
578 580 }
579 581
580 582 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len];
581 583 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
582 584
583 585 ack_high = dccpha->dha_seq;
584 586 ack_low = dccpha_ext->dha_ext_seq;
585 587
586 588 seq = ntohs(ack_high) << 31;
587 589 seq |= ntohl(ack_low);
588 590
589 591 dccp->dccp_isr = seq;
590 592 dccp->dccp_gsr = seq;
591 593 dccp->dccp_swl = seq;
592 594 dccp->dccp_swh = seq;
593 595 dccp->dccp_gss++;
594 596
595 597 error = dccp_generate_options(dccp, &options, &opt_len);
596 598 if (error != 0) {
597 599 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_options failed");
598 600 }
599 601 cmn_err(CE_NOTE, "generated options len: %d", (int) opt_len);
600 602
601 603
602 604 /*
603 605 * conn_ht_iphc_len = ip_hdr_length (20) + ulp_hdr_length
604 606 * (20) simple ip header (without vtag or options)
605 607 */
606 608 total_hdr_len = len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4 + opt_len;
607 609 mp1 = allocb(len, BPRI_MED);
608 610 if (mp1 == NULL) {
609 611 cmn_err(CE_NOTE, "allocb failed");
610 612 return (NULL);
611 613 }
612 614
613 615 rptr = mp1->b_rptr;
614 616 mp1->b_wptr = &mp1->b_rptr[len];
615 617
616 618 bcopy(options, &mp1->b_rptr[len-opt_len], opt_len);
617 619 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
618 620 dccpha = (dccpha_t *)&rptr[ip_hdr_len];
619 621
620 622 dccpha->dha_type = DCCP_PKT_RESPONSE;
621 623 dccpha->dha_offset = 7 + (opt_len / 4);
622 624 dccpha->dha_x = 1;
623 625 dccpha->dha_ccval = 0;
624 626 dccpha->dha_cscov = 0;
625 627 dccpha->dha_reserved = 0;
626 628 dccpha->dha_res_seq = 0;
627 629 dccpha->dha_seq = htons(dccp->dccp_gss >> 32);;
628 630 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t) + 4 + opt_len);
629 631
630 632
631 633 dccpha_ext = (dccpha_ext_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t)];
632 634 dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff);
633 635
634 636 dccpha_ack = (dccpha_ack_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t)];
635 637 dccpha_ack->dha_ack_high = ack_high;
636 638 dccpha_ack->dha_ack_low = ack_low;
637 639
638 640 dccpha_srv = (dccpha_srv_t *)&mp1->b_rptr[ip_hdr_len + sizeof (dccpha_t) + sizeof (dccpha_ext_t) + sizeof (dccpha_ack_t)];
639 641 dccpha_srv->dha_srv_code = 0;
640 642
641 643 ixa->ixa_pktlen = total_hdr_len;
642 644
643 645 if (ixa->ixa_flags & IXAF_IS_IPV4) {
644 646 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len);
645 647 } else {
646 648 ip6_t *ip6 = (ip6_t *)rptr;
647 649
648 650 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN);
649 651 }
650 652
651 653 cmn_err(CE_NOTE, "IPHC LEN: %d", connp->conn_ht_iphc_len);
652 654 cmn_err(CE_NOTE, "TOTAL LEN: %d", total_hdr_len);
653 655
654 656 kmem_free(options, opt_len);
655 657
656 658 return (mp1);
657 659 }
658 660
659 661 /*
660 662 * Generate a request packet. Must use 48-bit sequence
661 663 * numbers.
662 664 */
663 665 mblk_t *
664 666 dccp_generate_request(conn_t *connp)
665 667 {
666 668 dccp_t *dccp = connp->conn_dccp;
667 669 dccpha_t *dccpha;
668 670 dccpha_ext_t *dccpha_ext;
669 671 dccpha_srv_t *dccpha_srv;
670 672 ip_xmit_attr_t *ixa = connp->conn_ixa;
671 673 mblk_t *mp;
672 674 uchar_t *rptr;
673 675 uint_t total_hdr_len;
674 676 uint_t len;
675 677
676 678 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_request");
677 679
678 680 total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) +
679 681 sizeof (dccpha_srv_t);
680 682 mp = allocb(total_hdr_len, BPRI_MED);
681 683 if (mp == NULL) {
682 684 cmn_err(CE_NOTE, "allocb failed");
683 685 return (NULL);
684 686 }
685 687
686 688 rptr = mp->b_rptr;
687 689 mp->b_wptr = &mp->b_rptr[total_hdr_len];
688 690
689 691 /* Copy in the template header */
690 692 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
691 693
692 694 len = ixa->ixa_ip_hdr_length;
693 695 dccpha = (dccpha_t *)&rptr[len];
694 696 dccpha->dha_type = DCCP_PKT_REQUEST;
695 697 dccpha->dha_offset = (sizeof (dccpha_t) + sizeof (dccpha_ext_t) +
696 698 sizeof (dccpha_srv_t)) / 4;
697 699 dccpha->dha_x = 1;
698 700 dccpha->dha_ccval = 0;
699 701 dccpha->dha_cscov = 0;
700 702 dccpha->dha_reserved = 0;
701 703 dccpha->dha_res_seq = 0;
702 704 dccpha->dha_seq = 0;
703 705 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) +
704 706 sizeof (dccpha_srv_t));
705 707
706 708 /* Extended sequence number */
707 709 len += sizeof (dccpha_t);
708 710 dccpha_ext = (dccpha_ext_t *)&rptr[len];
709 711
710 712 /* Service number */
711 713 len += sizeof (dccpha_ext_t);
712 714 dccpha_srv = (dccpha_srv_t *)&rptr[len];
713 715 dccpha_srv->dha_srv_code = 0;
714 716
715 717 ixa->ixa_pktlen = total_hdr_len;
716 718
717 719 if (ixa->ixa_flags & IXAF_IS_IPV4) {
718 720 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len);
719 721 } else {
720 722 ip6_t *ip6 = (ip6_t *)rptr;
721 723
722 724 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN);
723 725 }
724 726
725 727 return (mp);
726 728 }
727 729
728 730 /*
729 731 * Close packet.
730 732 */
731 733 mblk_t *
732 734 dccp_generate_reset(conn_t *connp)
733 735 {
734 736 dccp_t *dccp = connp->conn_dccp;
735 737 dccpha_t *dccpha;
736 738 dccpha_ext_t *dccpha_ext;
737 739 dccpha_ack_t *dccpha_ack;
738 740 dccpha_reset_t *dccpha_reset;
739 741 ip_xmit_attr_t *ixa = connp->conn_ixa;
740 742 mblk_t *mp;
741 743 uint64_t gss;
742 744 uchar_t *rptr;
743 745 uint_t total_hdr_len;
744 746 uint_t len = ixa->ixa_ip_hdr_length;
745 747
746 748 cmn_err(CE_NOTE, "dccp_output.c: dccp_generate_reset");
747 749
748 750 /* XXX */
749 751 dccp->dccp_gss++;
750 752
751 753 /*
752 754 * Allocate a new DCCP reset message
753 755 */
754 756 total_hdr_len = connp->conn_ht_iphc_len + sizeof (dccpha_ext_t) +
755 757 sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t);
756 758 mp = allocb(total_hdr_len, BPRI_MED);
757 759 if (mp == NULL) {
758 760 cmn_err(CE_NOTE, "allocb failed");
759 761 return(NULL);
760 762 }
761 763
762 764 rptr = mp->b_rptr;
763 765 mp->b_wptr = &mp->b_rptr[total_hdr_len];
764 766
765 767 bcopy(connp->conn_ht_iphc, rptr, connp->conn_ht_iphc_len);
766 768
767 769 len = ixa->ixa_ip_hdr_length;
768 770 dccpha = (dccpha_t *)&mp->b_rptr[len];
769 771 dccpha->dha_type = DCCP_PKT_RESET;
770 772 dccpha->dha_offset = 7;
771 773 dccpha->dha_x = 1;
772 774 dccpha->dha_ccval = 0;
773 775 dccpha->dha_cscov = 0;
774 776 dccpha->dha_sum = htons(sizeof (dccpha_t) + sizeof (dccpha_ext_t) +
775 777 sizeof (dccpha_ack_t) + sizeof (dccpha_reset_t));
776 778 dccpha->dha_seq = htons(dccp->dccp_gss >> 32);
777 779
778 780 len += sizeof (dccpha_t);
779 781 dccpha_ext = (dccpha_ext_t *)&mp->b_rptr[len];
780 782 dccpha_ext->dha_ext_seq = htonl(dccp->dccp_gss & 0xffffffff);
781 783
782 784 len += sizeof (dccpha_ext_t);
783 785 dccpha_ack = (dccpha_ack_t *)&mp->b_rptr[len];
784 786 dccpha_ack->dha_ack_high = htons(dccp->dccp_gsr >> 32);
785 787 dccpha_ack->dha_ack_low = htonl(dccp->dccp_gsr & 0xffffffff);
786 788
787 789 len += sizeof (dccpha_ack_t);
788 790 dccpha_reset = (dccpha_reset_t *)&mp->b_rptr[len];
789 791 dccpha_reset->dha_reset_code = DCCP_RESET_CLOSED;
790 792 dccpha_reset->dha_reset_data[0] = 0;
791 793 dccpha_reset->dha_reset_data[1] = 0;
792 794 dccpha_reset->dha_reset_data[2] = 0;
793 795
794 796 ixa->ixa_pktlen = total_hdr_len;
795 797
796 798 if (ixa->ixa_flags & IXAF_IS_IPV4) {
797 799 cmn_err(CE_NOTE, "setting ip len for ipv4: %d", total_hdr_len);
798 800 ((ipha_t *)rptr)->ipha_length = htons(total_hdr_len);
799 801 } else {
800 802 ip6_t *ip6 = (ip6_t *)rptr;
801 803
802 804 ip6->ip6_plen = htons(total_hdr_len - IPV6_HDR_LEN);
803 805 }
804 806
805 807 return (mp);
806 808 }
↓ open down ↓ |
708 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX