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.c
+++ new/usr/src/uts/common/inet/dccp/dccp.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 * This file implements the Data Congestion Control Protocol (DCCP).
33 33 */
34 34
35 35 #include <sys/types.h>
36 36 #include <sys/stream.h>
37 37 #include <sys/stropts.h>
38 38 #include <sys/strlog.h>
39 39 #include <sys/strsun.h>
40 40 #define _SUN_TPI_VERSION 2
41 41 #include <sys/tihdr.h>
42 42 #include <sys/socket.h>
43 43 #include <sys/socketvar.h>
44 44 #include <sys/sockio.h>
45 45 #include <sys/priv.h>
46 46 #include <sys/vtrace.h>
47 47 #include <sys/sdt.h>
48 48 #include <sys/debug.h>
49 49 #include <sys/ddi.h>
50 50 #include <sys/isa_defs.h>
51 51 #include <sys/policy.h>
52 52 #include <sys/tsol/label.h>
53 53 #include <sys/tsol/tnet.h>
54 54 #include <inet/dccp_impl.h>
55 55 #include <inet/dccp_stack.h>
56 56 #include <inet/kstatcom.h>
57 57 #include <inet/snmpcom.h>
58 58
59 59 #include <sys/cmn_err.h>
60 60
61 61 int dccp_squeue_flag;
62 62
63 63 /* Setable in /etc/system */
64 64 uint_t dccp_bind_fanout_size = DCCP_BIND_FANOUT_SIZE;
65 65
66 66 static void dccp_notify(void *, ip_xmit_attr_t *, ixa_notify_type_t,
67 67 ixa_notify_arg_t);
68 68
69 69 /* Functions to register netstack */
70 70 static void *dccp_stack_init(netstackid_t, netstack_t *);
71 71 static void dccp_stack_fini(netstackid_t, void *);
72 72
73 73 /* Stream device open functions */
74 74 static int dccp_openv4(queue_t *, dev_t *, int, int, cred_t *);
75 75 static int dccp_openv6(queue_t *, dev_t *, int, int, cred_t *);
76 76 static int dccp_open(queue_t *, dev_t *, int, int, cred_t *,
77 77 boolean_t);
78 78
79 79 /* Write service routine */
80 80 static void dccp_wsrv(queue_t *);
81 81
82 82 /* Connection related functions */
83 83 static int dccp_connect_ipv4(dccp_t *, ipaddr_t *, in_port_t, uint_t);
84 84 static int dccp_connect_ipv6(dccp_t *, in6_addr_t *, in_port_t, uint32_t,
85 85 uint_t, uint32_t);
86 86
87 87 /* Initialise ISS */
88 88 static void dccp_iss_init(dccp_t *);
89 89
90 90 struct module_info dccp_rinfo = {
91 91 DCCP_MOD_ID, DCCP_MOD_NAME, 0, INFPSZ, DCCP_RECV_HIWATER,
92 92 DCCP_RECV_LOWATER
93 93 };
94 94
95 95 static struct module_info dccp_winfo = {
96 96 DCCP_MOD_ID, DCCP_MOD_NAME, 0, INFPSZ, 127, 16
97 97 };
98 98
99 99 /*
100 100 * Queue information structure with DCCP entry points.
101 101 */
102 102 struct qinit dccp_rinitv4 = {
103 103 NULL, (pfi_t)dccp_rsrv, dccp_openv4, dccp_tpi_close, NULL, &dccp_rinfo
104 104 };
105 105
106 106 struct qinit dccp_rinitv6 = {
107 107 NULL, (pfi_t)dccp_rsrv, dccp_openv6, dccp_tpi_close, NULL, &dccp_rinfo
108 108 };
109 109
110 110 struct qinit dccp_winit = {
111 111 (pfi_t)dccp_wput, (pfi_t)dccp_wsrv, NULL, NULL, NULL, &dccp_winfo
112 112 };
113 113
114 114 /* Initial entry point for TCP in socket mode */
115 115 struct qinit dccp_sock_winit = {
116 116 (pfi_t)dccp_wput_sock, (pfi_t)dccp_wsrv, NULL, NULL, NULL, &dccp_winfo
117 117 };
118 118
119 119 struct qinit dccp_fallback_sock_winit = {
120 120 (pfi_t)dccp_wput_fallback, NULL, NULL, NULL, NULL, &dccp_winfo
121 121 };
122 122 /*
123 123 * DCCP as acceptor STREAM.
124 124 */
125 125 struct qinit dccp_acceptor_rinit = {
126 126 NULL, (pfi_t)dccp_rsrv, NULL, dccp_tpi_close_accept, NULL, &dccp_winfo
127 127 };
128 128
129 129 struct qinit dccp_acceptor_winit = {
130 130 (pfi_t)dccp_tpi_accept, NULL, NULL, NULL, NULL, &dccp_winfo
131 131 };
132 132
133 133 /* AF_INET /dev/dccp */
134 134 struct streamtab dccpinfov4 = {
135 135 &dccp_rinitv4, &dccp_winit
136 136 };
137 137
138 138 /* AF_INET6 /dev/dccp6 */
139 139 struct streamtab dccpinfov6 = {
140 140 &dccp_rinitv6, &dccp_winit
141 141 };
142 142
143 143 /* Template for response to info request */
144 144 struct T_info_ack dccp_g_t_info_ack = {
145 145 T_INFO_ACK, /* PRIM_type */
146 146 0, /* TSDU_size */
147 147 T_INFINITE, /* ETSDU_size */
148 148 T_INVALID, /* CDATA_size */
149 149 T_INVALID, /* DDATA_size */
150 150 sizeof (sin_t), /* ADDR_size */
151 151 0, /* OPT_size - not initialized here */
152 152 TIDUSZ, /* TIDU_size */
153 153 T_COTS_ORD, /* SERV_type */
154 154 DCCPS_CLOSED, /* CURRENT_state */
155 155 (XPG4_1|EXPINLINE) /* PROVIDER_flag */
156 156 };
157 157
158 158 struct T_info_ack dccp_g_t_info_ack_v6 = {
159 159 T_INFO_ACK, /* PRIM_type */
160 160 0, /* TSDU_size */
161 161 T_INFINITE, /* ETSDU_size */
162 162 T_INVALID, /* CDATA_size */
163 163 T_INVALID, /* DDATA_size */
164 164 sizeof (sin6_t), /* ADDR_size */
165 165 0, /* OPT_size - not initialized here */
166 166 TIDUSZ, /* TIDU_size */
167 167 T_COTS_ORD, /* SERV_type */
168 168 DCCPS_CLOSED, /* CURRENT_state */
169 169 (XPG4_1|EXPINLINE) /* PROVIDER_flag */
170 170 };
171 171
172 172 /*
173 173 * DCCP Tunables.
174 174 */
175 175 extern mod_prop_info_t dccp_propinfo_tbl[];
176 176 extern int dccp_propinfo_count;
177 177
178 178 /*
179 179 * Register DCCP in ip netstack.
180 180 */
181 181 void
182 182 dccp_ddi_g_init(void)
183 183 {
184 184 /* Global timer cache */
185 185 dccp_timercache = kmem_cache_create("dccp_timercache",
186 186 sizeof (dccp_timer_t) + sizeof (mblk_t), 0,
187 187 NULL, NULL, NULL, NULL, NULL, 0);
188 188
189 189 netstack_register(NS_DCCP, dccp_stack_init, NULL, dccp_stack_fini);
190 190 }
191 191
192 192 /*
193 193 * Unregister DCCP from ip netstack.
194 194 */
195 195 void
196 196 dccp_ddi_g_destroy(void)
197 197 {
198 198 /* Global timer cache */
199 199 kmem_cache_destroy(dccp_timercache);
200 200
201 201 netstack_unregister(NS_DCCP);
202 202 }
203 203
204 204 #define INET_NAME "ip"
205 205
206 206 /*
207 207 * Initialize this DCCP stack instance.
208 208 */
209 209 static void *
210 210 dccp_stack_init(netstackid_t stackid, netstack_t *ns)
211 211 {
212 212 dccp_stack_t *dccps;
213 213 major_t major;
214 214 size_t arrsz;
215 215 int error;
216 216 int i;
217 217
218 218 dccps = kmem_zalloc(sizeof (*dccps), KM_SLEEP);
219 219 if (dccps == NULL) {
220 220 return (NULL);
221 221 }
222 222 dccps->dccps_netstack = ns;
223 223
224 224 /* Ports */
225 225 mutex_init(&dccps->dccps_epriv_port_lock, NULL, MUTEX_DEFAULT, NULL);
226 226 dccps->dccps_num_epriv_ports = DCCP_NUM_EPRIV_PORTS;
227 227 dccps->dccps_epriv_ports[0] = ULP_DEF_EPRIV_PORT1;
228 228 dccps->dccps_epriv_ports[1] = ULP_DEF_EPRIV_PORT2;
229 229 dccps->dccps_min_anonpriv_port = 512;
230 230
231 231 dccps->dccps_bind_fanout_size = dccp_bind_fanout_size;
232 232
233 233 /* Bind fanout */
234 234 dccps->dccps_bind_fanout = kmem_zalloc(dccps->dccps_bind_fanout_size *
235 235 sizeof (dccp_df_t), KM_SLEEP);
236 236 for (i = 0; i < dccps->dccps_bind_fanout_size; i++) {
237 237 mutex_init(&dccps->dccps_bind_fanout[i].df_lock, NULL,
238 238 MUTEX_DEFAULT, NULL);
239 239 }
240 240
241 241 /* Tunable properties */
242 242 arrsz = dccp_propinfo_count * sizeof (mod_prop_info_t);
243 243 dccps->dccps_propinfo_tbl = kmem_alloc(arrsz, KM_SLEEP);
244 244 if (dccps->dccps_propinfo_tbl == NULL) {
245 245 kmem_free(dccps, sizeof (*dccps));
246 246 return (NULL);
247 247 }
248 248 bcopy(dccp_propinfo_tbl, dccps->dccps_propinfo_tbl, arrsz);
249 249
250 250 /* Allocate per netstack cpu stats */
251 251 mutex_enter(&cpu_lock);
252 252 dccps->dccps_sc_cnt = MAX(ncpus, boot_ncpus);
↓ open down ↓ |
252 lines elided |
↑ open up ↑ |
253 253 mutex_exit(&cpu_lock);
254 254
255 255 dccps->dccps_sc = kmem_zalloc(max_ncpus * sizeof (dccp_stats_cpu_t *),
256 256 KM_SLEEP);
257 257 for (i = 0; i < dccps->dccps_sc_cnt; i++) {
258 258 dccps->dccps_sc[i] = kmem_zalloc(sizeof (dccp_stats_cpu_t),
259 259 KM_SLEEP);
260 260 }
261 261
262 262 /* Kernel statistics */
263 - dccps->dccps_kstat = dccp_kstat2_init(stackid);
264 - dccps->dccps_mibkp = dccp_kstat_init(stackid);
263 + //dccps->dccps_kstat = dccp_kstat2_init(stackid);
264 + //dccps->dccps_mibkp = dccp_kstat_init(stackid);
265 265
266 266 /* Driver major number */
267 267 major = mod_name_to_major(INET_NAME);
268 268 error = ldi_ident_from_major(major, &dccps->dccps_ldi_ident);
269 269 ASSERT(error == 0);
270 270
271 271 return (dccps);
272 272 }
273 273
274 274 /*
275 275 * Destroy this DCCP netstack instance.
276 276 */
277 277 static void
278 278 dccp_stack_fini(netstackid_t stackid, void *arg)
279 279 {
280 280 dccp_stack_t *dccps = (dccp_stack_t *)arg;
281 281 int i;
282 282
283 283 /* Free cpu stats */
284 284 for (i = 0; i < dccps->dccps_sc_cnt; i++) {
285 285 kmem_free(dccps->dccps_sc[i], sizeof (dccp_stats_cpu_t));
286 286 }
287 287 kmem_free(dccps->dccps_sc, max_ncpus * sizeof (dccp_stats_cpu_t *));
288 288
289 289 /* Free tunable properties */
290 290 kmem_free(dccps->dccps_propinfo_tbl,
291 291 dccp_propinfo_count * sizeof (mod_prop_info_t));
292 292 dccps->dccps_propinfo_tbl = NULL;
293 293
294 294 /* Free bind fanout */
295 295 for (i = 0; i < dccps->dccps_bind_fanout_size; i++) {
↓ open down ↓ |
21 lines elided |
↑ open up ↑ |
296 296 ASSERT(dccps->dccps_bind_fanout[i].df_dccp == NULL);
297 297 mutex_destroy(&dccps->dccps_bind_fanout[i].df_lock);
298 298 }
299 299 kmem_free(dccps->dccps_bind_fanout, dccps->dccps_bind_fanout_size *
300 300 sizeof (dccp_df_t));
301 301 dccps->dccps_bind_fanout = NULL;
302 302
303 303 /* Kernel statistics */
304 304 dccp_kstat_fini(stackid, dccps->dccps_mibkp);
305 305 dccps->dccps_mibkp = NULL;
306 + dccp_kstat2_fini(stackid, dccps->dccps_kstat);
307 + dccps->dccps_kstat = NULL;
306 308
307 309 ldi_ident_release(dccps->dccps_ldi_ident);
308 310
309 311 kmem_free(dccps, sizeof (*dccps));
310 312 }
311 313
312 314 /* /dev/dccp */
313 315 static int
314 316 dccp_openv4(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
315 317 {
316 318 cmn_err(CE_NOTE, "dccp.c: dccp_openv4\n");
317 319
318 320 return (dccp_open(q, devp, flag, sflag, credp, B_FALSE));
319 321 }
320 322
321 323 /* /dev/dccp6 */
322 324 static int
323 325 dccp_openv6(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
324 326 {
325 327 cmn_err(CE_NOTE, "dccp.c: dccp_openv6\n");
326 328
327 329 return (dccp_open(q, devp, flag, sflag, credp, B_TRUE));
328 330 }
329 331
330 332 /*
331 333 * Common open function for v4 and v6 devices.
332 334 */
333 335 static int
334 336 dccp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp,
335 337 boolean_t isv6)
336 338 {
337 339 conn_t *connp;
338 340 dccp_t *dccp;
339 341 vmem_t *minor_arena;
340 342 dev_t conn_dev;
341 343 boolean_t issocket;
342 344 int error;
343 345
344 346 cmn_err(CE_NOTE, "dccp.c: dccp_open");
345 347
346 348 /* If the stream is already open, return immediately */
347 349 if (q->q_ptr != NULL) {
348 350 return (0);
349 351 }
350 352
351 353 if (sflag == MODOPEN) {
352 354 return (EINVAL);
353 355 }
354 356
355 357 if ((ip_minor_arena_la != NULL) && (flag & SO_SOCKSTR) &&
356 358 ((conn_dev = inet_minor_alloc(ip_minor_arena_la)) != 0)) {
357 359 minor_arena = ip_minor_arena_la;
358 360 } else {
359 361 /*
360 362 * Either minor numbers in the large arena were exhausted
361 363 * or a non socket application is doing the open.
362 364 * Try to allocate from the small arena.
363 365 */
364 366 if ((conn_dev = inet_minor_alloc(ip_minor_arena_sa)) == 0) {
365 367 return (EBUSY);
366 368 }
367 369 minor_arena = ip_minor_arena_sa;
368 370 }
369 371
370 372 ASSERT(minor_arena != NULL);
371 373
372 374 *devp = makedevice(getmajor(*devp), (minor_t)conn_dev);
373 375
374 376 if (flag & SO_FALLBACK) {
375 377 /*
376 378 * Non streams socket needs a stream to fallback to.
377 379 */
378 380 RD(q)->q_ptr = (void *)conn_dev;
379 381 WR(q)->q_qinfo = &dccp_fallback_sock_winit;
380 382 WR(q)->q_ptr = (void *)minor_arena;
381 383 qprocson(q);
382 384 return (0);
383 385 } else if (flag & SO_ACCEPTOR) {
384 386 q->q_qinfo = &dccp_acceptor_rinit;
385 387 /*
386 388 * The conn_dev and minor_arena will be subsequently used by
387 389 * dccp_tli_accept() and dccp_tpi_close_accept() to figure out
388 390 * the minor device number for this connection from the q_ptr.
389 391 */
390 392 RD(q)->q_ptr = (void *)conn_dev;
391 393 WR(q)->q_qinfo = &dccp_acceptor_winit;
392 394 WR(q)->q_ptr = (void *)minor_arena;
393 395 qprocson(q);
394 396 return (0);
395 397 }
396 398
397 399 issocket = flag & SO_SOCKSTR;
398 400 connp = dccp_create_common(credp, isv6, issocket, &error);
399 401 if (connp == NULL) {
400 402 inet_minor_free(minor_arena, conn_dev);
401 403 q->q_ptr = WR(q)->q_ptr = NULL;
402 404 return (error);
403 405 }
404 406
405 407 connp->conn_rq = q;
406 408 connp->conn_wq = WR(q);
407 409 q->q_ptr = WR(q)->q_ptr = connp;
408 410
409 411 connp->conn_dev = conn_dev;
410 412 connp->conn_minor_arena = minor_arena;
411 413
412 414 ASSERT(q->q_qinfo == &dccp_rinitv4 || q->q_qinfo == &dccp_rinitv6);
413 415 ASSERT(WR(q)->q_qinfo == &dccp_winit);
414 416
415 417 dccp = connp->conn_dccp;
416 418
417 419 if (issocket) {
418 420 WR(q)->q_qinfo = &dccp_sock_winit;
419 421 } else {
420 422 #ifdef _ILP32
421 423 dccp->dccp_acceptor_id = (t_uscalar_t)RD(q);
422 424 #else
423 425 dccp->dccp_acceptor_id = conn_dev;
424 426 #endif /* _ILP32 */
425 427 }
426 428
427 429 /*
428 430 * Put the ref for DCCP. Ref for IP was already put
429 431 * by ipcl_conn_create. Also Make the conn_t globally
430 432 * visible to walkers.
431 433 */
432 434 mutex_enter(&connp->conn_lock);
433 435 CONN_INC_REF_LOCKED(connp);
434 436 ASSERT(connp->conn_ref == 2);
435 437 connp->conn_state_flags &= ~CONN_INCIPIENT;
436 438 mutex_exit(&connp->conn_lock);
437 439
438 440 qprocson(q);
439 441
440 442 return (0);
441 443 }
442 444
443 445 /*
444 446 * IXA notify
445 447 */
446 448 static void
447 449 dccp_notify(void *arg, ip_xmit_attr_t *ixa, ixa_notify_type_t ntype,
448 450 ixa_notify_arg_t narg)
449 451 {
450 452 cmn_err(CE_NOTE, "dccp.c: dccp_notify");
451 453 }
452 454
453 455 /*
454 456 * Build the template headers.
455 457 */
456 458 int
457 459 dccp_build_hdrs(dccp_t *dccp)
458 460 {
459 461 dccp_stack_t *dccps = dccp->dccp_dccps;
460 462 conn_t *connp = dccp->dccp_connp;
461 463 dccpha_t *dccpha;
462 464 uint32_t cksum;
463 465 char buf[DCCP_MAX_HDR_LENGTH];
464 466 uint_t buflen;
465 467 uint_t ulplen = 12;
466 468 uint_t extralen = 0;
467 469 int error;
468 470
469 471 cmn_err(CE_NOTE, "dccp.c: dccp_build_hdrs");
470 472
471 473 buflen = connp->conn_ht_ulp_len;
472 474 if (buflen != 0) {
473 475 cmn_err(CE_NOTE, "buflen != 0");
474 476 bcopy(connp->conn_ht_ulp, buf, buflen);
475 477 extralen -= buflen - ulplen;
476 478 ulplen = buflen;
477 479 }
478 480
479 481 mutex_enter(&connp->conn_lock);
480 482 error = conn_build_hdr_template(connp, ulplen, extralen,
481 483 &connp->conn_laddr_v6, &connp->conn_faddr_v6, connp->conn_flowinfo);
482 484 mutex_exit(&connp->conn_lock);
483 485 if (error != 0) {
484 486 cmn_err(CE_NOTE, "conn_build_hdr_template failed");
485 487 return (error);
486 488 }
487 489
488 490 dccpha = (dccpha_t *)connp->conn_ht_ulp;
489 491 dccp->dccp_dccpha = dccpha;
490 492
491 493 if (buflen != 0) {
492 494 bcopy(buf, connp->conn_ht_ulp, buflen);
493 495 } else {
494 496 dccpha->dha_sum = 0;
495 497 dccpha->dha_lport = connp->conn_lport;
496 498 dccpha->dha_fport = connp->conn_fport;
497 499 }
498 500
499 501 cksum = sizeof (dccpha_t) + connp->conn_sum;
500 502 cksum = (cksum >> 16) + (cksum & 0xFFFF);
501 503 dccpha->dha_sum = htons(cksum);
502 504 dccpha->dha_offset = 7;
503 505 dccpha->dha_x = 1;
504 506
505 507 if (connp->conn_ipversion == IPV4_VERSION) {
506 508 dccp->dccp_ipha = (ipha_t *)connp->conn_ht_iphc;
507 509 } else {
508 510 dccp->dccp_ip6h = (ip6_t *)connp->conn_ht_iphc;
509 511 }
510 512
511 513 /* XXX */
512 514
513 515 return (0);
514 516 }
515 517
516 518 /*
517 519 * DCCP write service routine.
518 520 */
519 521 static void
520 522 dccp_wsrv(queue_t *q)
521 523 {
522 524 dccp_stack_t *dccps = Q_TO_DCCP(q)->dccp_dccps;
523 525
524 526 DCCP_STAT(dccps, dccp_wsrv_called);
525 527 }
526 528
527 529 /*
528 530 * Common create function for streams and sockets.
529 531 */
530 532 conn_t *
531 533 dccp_create_common(cred_t *credp, boolean_t isv6, boolean_t issocket,
532 534 int *errorp)
533 535 {
534 536 conn_t *connp;
535 537 dccp_t *dccp;
536 538 dccp_stack_t *dccps;
537 539 netstack_t *ns;
538 540 squeue_t *sqp;
539 541 zoneid_t zoneid;
540 542 int error;
541 543
542 544 cmn_err(CE_NOTE, "dccp.c: dccp_create_common\n");
543 545
544 546 ASSERT(errorp != NULL);
545 547
546 548 error = secpolicy_basic_net_access(credp);
547 549 if (error != 0) {
548 550 *errorp = error;
549 551 return (NULL);
550 552 }
551 553
552 554 /*
553 555 * Find the right netstack.
554 556 */
555 557 ns = netstack_find_by_cred(credp);
556 558 ASSERT(ns != NULL);
557 559 dccps = ns->netstack_dccp;
558 560 ASSERT(dccps != NULL);
559 561
560 562 /*
561 563 * For exclusive stacks we set the zoneid to zero
562 564 * to make TCP operate as if in the global zone.
563 565 */
564 566 if (ns->netstack_stackid != GLOBAL_NETSTACKID) {
565 567 zoneid = GLOBAL_ZONEID;
566 568 } else {
567 569 zoneid = crgetzoneid(credp);
568 570 }
569 571
570 572 sqp = IP_SQUEUE_GET((uint_t)gethrtime());
571 573 connp = (conn_t *)dccp_get_conn(sqp, dccps);
572 574 netstack_rele(dccps->dccps_netstack);
573 575 if (connp == NULL) {
574 576 *errorp = ENOSR;
575 577 return (NULL);
576 578 }
577 579 ASSERT(connp->conn_ixa->ixa_protocol == connp->conn_proto);
578 580
579 581 connp->conn_sqp = sqp;
580 582 connp->conn_initial_sqp = connp->conn_sqp;
581 583 connp->conn_ixa->ixa_sqp = connp->conn_sqp;
582 584 dccp = connp->conn_dccp;
583 585
584 586 /* Setting flags for ip output */
585 587 connp->conn_ixa->ixa_flags |= IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE |
586 588 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO;
587 589
588 590 ASSERT(connp->conn_proto == IPPROTO_DCCP);
589 591 ASSERT(connp->conn_dccp == dccp);
590 592 ASSERT(dccp->dccp_connp == connp);
591 593
592 594 if (isv6) {
593 595 connp->conn_ixa->ixa_src_preferences = IPV6_PREFER_SRC_DEFAULT;
594 596 connp->conn_ipversion = IPV6_VERSION;
595 597 connp->conn_family = AF_INET6;
596 598 /* XXX mms, ttl */
597 599 } else {
598 600 connp->conn_ipversion = IPV4_VERSION;
599 601 connp->conn_family = AF_INET;
600 602 /* XXX mms, ttl */
601 603 }
602 604 connp->conn_xmit_ipp.ipp_unicast_hops = connp->conn_default_ttl;
603 605
604 606 crhold(credp);
605 607 connp->conn_cred = credp;
606 608 connp->conn_cpid = curproc->p_pid;
607 609 connp->conn_open_time = ddi_get_lbolt64();
608 610
609 611 ASSERT(!(connp->conn_ixa->ixa_free_flags & IXA_FREE_CRED));
610 612 connp->conn_ixa->ixa_cred = credp;
611 613 connp->conn_ixa->ixa_cpid = connp->conn_cpid;
612 614
613 615 connp->conn_zoneid = zoneid;
614 616 connp->conn_zone_is_global = (crgetzoneid(credp) == GLOBAL_ZONEID);
615 617 connp->conn_ixa->ixa_zoneid = zoneid;
616 618 connp->conn_mlp_type = mlptSingle;
617 619
618 620 dccp->dccp_dccps = dccps;
619 621 dccp->dccp_state = DCCPS_CLOSED;
620 622
621 623 ASSERT(connp->conn_netstack == dccps->dccps_netstack);
622 624 ASSERT(dccp->dccp_dccps == dccps);
623 625
624 626 /*
625 627 * If the caller has the process-wide flag set, then default to MAC
626 628 * exempt mode. This allows read-down to unlabeled hosts.
627 629 */
628 630 if (getpflags(NET_MAC_AWARE, credp) != 0) {
629 631 connp->conn_mac_mode = CONN_MAC_AWARE;
630 632 }
631 633
632 634 if (issocket) {
633 635 dccp->dccp_issocket = 1;
634 636 }
635 637
636 638 /* XXX rcvbuf, sndbuf etc */
637 639
638 640 connp->conn_so_type = SOCK_STREAM;
639 641
640 642 SOCK_CONNID_INIT(dccp->dccp_connid);
641 643 dccp_init_values(dccp, NULL);
642 644
643 645 return (connp);
644 646 }
645 647
646 648 /*
647 649 * Common close function for streams and sockets.
648 650 */
649 651 void
650 652 dccp_close_common(conn_t *connp, int flags)
651 653 {
652 654 dccp_t *dccp = connp->conn_dccp;
653 655 mblk_t *mp;
654 656 boolean_t conn_ioctl_cleanup_reqd = B_FALSE;
655 657
656 658 cmn_err(CE_NOTE, "dccp.c: dccp_close_common");
657 659
658 660 ASSERT(connp->conn_ref >= 2);
659 661
660 662 /*
661 663 * Mark the conn as closing. ipsq_pending_mp_add will not
662 664 * add any mp to the pending mp list, after this conn has
663 665 * started closing.
664 666 */
665 667 mutex_enter(&connp->conn_lock);
666 668 connp->conn_state_flags |= CONN_CLOSING;
667 669
668 670 if (connp->conn_oper_pending_ill != NULL) {
669 671 conn_ioctl_cleanup_reqd = B_TRUE;
670 672 }
671 673
672 674 CONN_INC_REF_LOCKED(connp);
673 675 mutex_exit(&connp->conn_lock);
674 676
675 677 ASSERT(connp->conn_ref >= 3);
676 678
677 679 /*
678 680 * Cleanup any queued ioctls here. This must be done before the wq/rq
679 681 * are re-written by dccp_close_output().
680 682 */
681 683 if (conn_ioctl_cleanup_reqd) {
682 684 conn_ioctl_cleanup(connp);
683 685 }
684 686
685 687 mutex_enter(&connp->conn_lock);
686 688 while (connp->conn_ioctlref > 0) {
687 689 cv_wait(&connp->conn_cv, &connp->conn_lock);
688 690 }
689 691 ASSERT(connp->conn_ioctlref == 0);
690 692 ASSERT(connp->conn_oper_pending_ill == NULL);
691 693 mutex_exit(&connp->conn_lock);
692 694
693 695 /* generate close */
694 696 /*
695 697 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, dccp_close_output, connp,
696 698 NULL, dccp_squeue_flag, SQTAG_IP_DCCP_CLOSE);
697 699
698 700 */
699 701
700 702 nowait:
701 703 connp->conn_cpid = NOPID;
702 704 }
703 705
704 706 /*
705 707 * Common bind function.
706 708 */
707 709 int
708 710 dccp_do_bind(conn_t *connp, struct sockaddr *sa, socklen_t len, cred_t *cr,
709 711 boolean_t bind_to_req_port_only)
710 712 {
711 713 dccp_t *dccp = connp->conn_dccp;
712 714 int error;
713 715
714 716 cmn_err(CE_NOTE, "dccp.c: dccp_do_bind");
715 717
716 718 if (dccp->dccp_state >= DCCPS_BOUND) {
717 719 if (connp->conn_debug) {
718 720 (void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
719 721 "dccp_bind: bad state, %d", dccp->dccp_state);
720 722 }
721 723 return (-TOUTSTATE);
722 724 }
723 725
724 726 error = dccp_bind_check(connp, sa, len, cr, bind_to_req_port_only);
725 727 if (error != 0) {
726 728 return (error);
727 729 }
728 730
729 731 ASSERT(dccp->dccp_state == DCCPS_LISTEN);
730 732 /* XXX dccp_conn_req_max = 0 */
731 733
732 734 return (0);
733 735 }
734 736
735 737 /*
736 738 * Common unbind function.
737 739 */
738 740 int
739 741 dccp_do_unbind(conn_t *connp)
740 742 {
741 743 dccp_t *dccp = connp->conn_dccp;
742 744 int32_t oldstate;
743 745
744 746 cmn_err(CE_NOTE, "dccp.c: dccp_do_unbind");
745 747
746 748 switch (dccp->dccp_state) {
747 749 case DCCPS_OPEN:
748 750 case DCCPS_LISTEN:
749 751 break;
750 752 default:
751 753 return (-TOUTSTATE);
752 754 }
753 755
754 756 connp->conn_laddr_v6 = ipv6_all_zeros;
755 757 connp->conn_saddr_v6 = ipv6_all_zeros;
756 758
757 759 dccp_bind_hash_remove(dccp);
758 760
759 761 oldstate = dccp->dccp_state;
760 762 dccp->dccp_state = DCCPS_CLOSED;
761 763 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *,
762 764 connp->conn_ixa, void, NULL, dccp_t *, dccp, void, NULL,
763 765 int32_t, oldstate);
764 766
765 767 ip_unbind(connp);
766 768 bzero(&connp->conn_ports, sizeof (connp->conn_ports));
767 769
768 770 return (0);
769 771 }
770 772
771 773 /*
772 774 * Common listen function.
773 775 */
774 776 int
775 777 dccp_do_listen(conn_t *connp, struct sockaddr *sa, socklen_t len,
776 778 int backlog, cred_t *cr, boolean_t bind_to_req_port_only)
777 779 {
778 780 dccp_t *dccp = connp->conn_dccp;
779 781 dccp_stack_t *dccps = dccp->dccp_dccps;
780 782 int32_t oldstate;
781 783 int error;
782 784
783 785 cmn_err(CE_NOTE, "dccp.c: dccp_do_listen");
784 786
785 787 /* All Solaris components should pass a cred for this operation */
786 788 ASSERT(cr != NULL);
787 789
788 790 if (dccp->dccp_state >= DCCPS_BOUND) {
789 791
790 792 if ((dccp->dccp_state == DCCPS_BOUND ||
791 793 dccp->dccp_state == DCCPS_LISTEN) && backlog > 0) {
792 794 goto do_listen;
793 795 }
794 796 cmn_err(CE_NOTE, "DCCPS_BOUND, bad state");
795 797
796 798 if (connp->conn_debug) {
797 799 (void) strlog(DCCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
798 800 "dccp_listen: bad state, %d", dccp->dccp_state);
799 801 }
800 802 return (-TOUTSTATE);
801 803 } else {
802 804 if (sa == NULL) {
803 805 sin6_t addr;
804 806 sin6_t *sin6;
805 807 sin_t *sin;
806 808
807 809 ASSERT(IPCL_IS_NONSTR(connp));
808 810
809 811 if (connp->conn_family == AF_INET) {
810 812 len = sizeof (sin_t);
811 813 sin = (sin_t *)&addr;
812 814 *sin = sin_null;
813 815 sin->sin_family = AF_INET;
814 816 } else {
815 817 ASSERT(connp->conn_family == AF_INET6);
816 818
817 819 len = sizeof (sin6_t);
818 820 sin6 = (sin6_t *)&addr;
819 821 *sin6 = sin6_null;
820 822 sin6->sin6_family = AF_INET6;
821 823 }
822 824
823 825 sa = (struct sockaddr *)&addr;
824 826 }
825 827
826 828 error = dccp_bind_check(connp, sa, len, cr,
827 829 bind_to_req_port_only);
828 830 if (error != 0) {
829 831 cmn_err(CE_NOTE, "dccp_bind_check failed");
830 832 return (error);
831 833 }
832 834 /* Fall through and do the fanout insertion */
833 835 }
834 836
835 837 do_listen:
836 838 ASSERT(dccp->dccp_state == DCCPS_BOUND ||
837 839 dccp->dccp_state == DCCPS_LISTEN);
838 840
839 841 /* XXX backlog */
840 842
841 843 connp->conn_recv = dccp_input_listener_unbound;
842 844
843 845 /* Insert into the classifier table */
844 846 error = ip_laddr_fanout_insert(connp);
845 847 if (error != 0) {
846 848 /* Error - undo the bind */
847 849 oldstate = dccp->dccp_state;
848 850 dccp->dccp_state = DCCPS_CLOSED;
849 851
850 852 connp->conn_bound_addr_v6 = ipv6_all_zeros;
851 853
852 854 connp->conn_laddr_v6 = ipv6_all_zeros;
853 855 connp->conn_saddr_v6 = ipv6_all_zeros;
854 856 connp->conn_ports = 0;
855 857
856 858 if (connp->conn_anon_port) {
857 859 zone_t *zone;
858 860
859 861 zone = crgetzone(cr);
860 862 connp->conn_anon_port = B_FALSE;
861 863 (void) tsol_mlp_anon(zone, connp->conn_mlp_type,
862 864 connp->conn_proto, connp->conn_lport, B_FALSE);
863 865 }
864 866 connp->conn_mlp_type = mlptSingle;
865 867
866 868 /* XXX dccp_bind_hash_remove */
867 869
868 870 return (error);
869 871 } else {
870 872 /* XXX connection limits */
871 873 }
872 874
873 875 return (error);
874 876 }
875 877
876 878 /*
877 879 * Common connect function.
878 880 */
879 881 int
880 882 dccp_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len,
881 883 cred_t *cr, pid_t pid)
882 884 {
883 885 dccp_t *dccp = connp->conn_dccp;
884 886 dccp_stack_t *dccps = dccp->dccp_dccps;
885 887 ip_xmit_attr_t *ixa = connp->conn_ixa;
886 888 mblk_t *req_mp;
887 889 sin_t *sin = (sin_t *)sa;
888 890 sin6_t *sin6 = (sin6_t *)sa;
889 891 ipaddr_t *dstaddrp;
890 892 in_port_t dstport;
891 893 uint_t srcid;
892 894 int32_t oldstate;
893 895 int error;
894 896
895 897 cmn_err(CE_NOTE, "dccp.c: dccp_do_connect");
896 898
897 899 oldstate = dccp->dccp_state;
898 900
899 901 switch (len) {
900 902 case sizeof (sin_t):
901 903 sin = (sin_t *)sa;
902 904 if (sin->sin_port == 0) {
903 905 return (-TBADADDR);
904 906 }
905 907 if (connp->conn_ipv6_v6only) {
906 908 return (EAFNOSUPPORT);
907 909 }
908 910 break;
909 911
910 912 case sizeof (sin6_t):
911 913 sin6 = (sin6_t *)sa;
912 914 if (sin6->sin6_port == 0) {
913 915 return (-TBADADDR);
914 916 }
915 917 break;
916 918
917 919 default:
918 920 return (EINVAL);
919 921 }
920 922
921 923 if (connp->conn_family == AF_INET6 &&
922 924 connp->conn_ipversion == IPV6_VERSION &&
923 925 IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
924 926 if (connp->conn_ipv6_v6only) {
925 927 return (EADDRNOTAVAIL);
926 928 }
927 929
928 930 connp->conn_ipversion = IPV4_VERSION;
929 931 }
930 932
931 933 switch (dccp->dccp_state) {
932 934 case DCCPS_LISTEN:
933 935 /*
934 936 * Listening sockets are not allowed to issue connect().
935 937 */
936 938 if (IPCL_IS_NONSTR(connp)) {
937 939 return (EOPNOTSUPP);
938 940 }
939 941
940 942 case DCCPS_CLOSED:
941 943 /*
942 944 * We support quick connect.
943 945 */
944 946 /* FALLTHRU */
945 947 case DCCPS_OPEN:
946 948 break;
947 949
948 950 default:
949 951 return (-TOUTSTATE);
950 952 }
951 953
952 954 /*
953 955 * We update our cred/cpid based on the caller of connect.
954 956 */
955 957 if (connp->conn_cred != cr) {
956 958 crhold(cr);
957 959 crfree(connp->conn_cred);
958 960 connp->conn_cred = cr;
959 961 }
960 962 connp->conn_cpid = pid;
961 963
962 964 /* Cache things in the ixa without any refhold */
963 965 ASSERT(!(ixa->ixa_free_flags & IXA_FREE_CRED));
964 966 ixa->ixa_cred = cr;
965 967 ixa->ixa_cpid = pid;
966 968
967 969 if (is_system_labeled()) {
968 970 ip_xmit_attr_restore_tsl(ixa, ixa->ixa_cred);
969 971 }
970 972
971 973 if (connp->conn_family == AF_INET6) {
972 974 if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
973 975 error = dccp_connect_ipv6(dccp, &sin6->sin6_addr,
974 976 sin6->sin6_port, sin6->sin6_flowinfo,
975 977 sin6->__sin6_src_id, sin6->sin6_scope_id);
976 978 } else {
977 979 /*
978 980 * Destination adress is mapped IPv6 address.
979 981 * Source bound address should be unspecified or
980 982 * IPv6 mapped address as well.
981 983 */
982 984 if (!IN6_IS_ADDR_UNSPECIFIED(
983 985 &connp->conn_bound_addr_v6) &&
984 986 !IN6_IS_ADDR_V4MAPPED(&connp->conn_bound_addr_v6)) {
985 987 return (EADDRNOTAVAIL);
986 988 }
987 989
988 990 dstaddrp = &V4_PART_OF_V6((sin6->sin6_addr));
989 991 dstport = sin6->sin6_port;
990 992 srcid = sin6->__sin6_src_id;
991 993 error = dccp_connect_ipv4(dccp, dstaddrp, dstport,
992 994 srcid);
993 995 }
994 996 } else {
995 997 dstaddrp = &sin->sin_addr.s_addr;
996 998 dstport = sin->sin_port;
997 999 srcid = 0;
998 1000 error = dccp_connect_ipv4(dccp, dstaddrp, dstport, srcid);
999 1001 }
1000 1002
1001 1003 if (error != 0) {
1002 1004 cmn_err(CE_NOTE, "dccp_connect_ip failed");
1003 1005 goto connect_failed;
1004 1006 }
1005 1007
1006 1008 /* XXX cluster */
1007 1009
1008 1010 /* Connect succeeded */
1009 1011 DCCPS_BUMP_MIB(dccps, dccpActiveOpens);
1010 1012 dccp->dccp_active_open = 1;
1011 1013
1012 1014 DTRACE_DCCP6(state__change, void, NULL, ip_xmit_attr_t *,
1013 1015 connp->conn_ixa, void, NULL, dccp_t *, dccp, void, NULL,
1014 1016 int32_t, DCCPS_BOUND);
1015 1017
1016 1018 DCCP_TIMER_RESTART(dccp, 100);
1017 1019 req_mp = dccp_generate_request(connp);
1018 1020 if (req_mp != NULL) {
1019 1021 /*
1020 1022 * We must bump the generation before sending the request
1021 1023 * to ensure that we use the right generation in case
1022 1024 * this thread issues a "connected" up call.
1023 1025 */
1024 1026 SOCK_CONNID_BUMP(dccp->dccp_connid);
1025 1027
1026 1028 DTRACE_DCCP5(connect__request, mblk_t *, NULL,
1027 1029 ip_xmit_attr_t *, connp->conn_ixa,
1028 1030 void_ip_t *, req_mp->b_rptr, dccp_t *, dccp,
1029 1031 dccpha_t *,
1030 1032 &req_mp->b_rptr[connp->conn_ixa->ixa_ip_hdr_length]);
1031 1033
1032 1034 dccp_send_data(dccp, req_mp);
1033 1035 }
1034 1036
1035 1037 return (0);
1036 1038
1037 1039 connect_failed:
1038 1040 cmn_err(CE_NOTE, "dccp_do_connect failed");
1039 1041
1040 1042 connp->conn_faddr_v6 = ipv6_all_zeros;
1041 1043 connp->conn_fport = 0;
1042 1044 dccp->dccp_state = oldstate;
1043 1045
1044 1046 /* XXX */
1045 1047 return (error);
1046 1048 }
1047 1049
1048 1050 /*
1049 1051 * Init values of a connection.
1050 1052 */
1051 1053 void
1052 1054 dccp_init_values(dccp_t *dccp, dccp_t *parent)
1053 1055 {
1054 1056 conn_t *connp = dccp->dccp_connp;
1055 1057 dccp_stack_t *dccps = dccp->dccp_dccps;
1056 1058
1057 1059 connp->conn_mlp_type = mlptSingle;
1058 1060 }
1059 1061
1060 1062 /*
1061 1063 * Free dccp structure.
1062 1064 */
1063 1065 void
1064 1066 dccp_free(dccp_t *dccp)
1065 1067 {
1066 1068 conn_t *connp = dccp->dccp_connp;
1067 1069
1068 1070 cmn_err(CE_NOTE, "dccp.c: dccp_free");
1069 1071
1070 1072 connp->conn_rq = NULL;
1071 1073 connp->conn_wq = NULL;
1072 1074
1073 1075 if (connp->conn_upper_handle != NULL) {
1074 1076 if (IPCL_IS_NONSTR(connp)) {
1075 1077 (*connp->conn_upcalls->su_closed)(
1076 1078 connp->conn_upper_handle);
1077 1079 dccp->dccp_detached = B_TRUE;
1078 1080 }
1079 1081
1080 1082 connp->conn_upper_handle = NULL;
1081 1083 connp->conn_upcalls = NULL;
1082 1084 }
1083 1085 }
1084 1086
1085 1087 void *
1086 1088 dccp_get_conn(void *arg, dccp_stack_t *dccps)
1087 1089 {
1088 1090 dccp_t *dccp = NULL;
1089 1091 conn_t *connp;
1090 1092 squeue_t *sqp = (squeue_t *)arg;
1091 1093 netstack_t *ns;
1092 1094
1093 1095 /* XXX timewait */
1094 1096
1095 1097 connp = ipcl_conn_create(IPCL_DCCPCONN, KM_NOSLEEP,
1096 1098 dccps->dccps_netstack);
1097 1099 if (connp == NULL) {
1098 1100 return (NULL);
1099 1101 }
1100 1102
1101 1103 dccp = connp->conn_dccp;
1102 1104 dccp->dccp_dccps = dccps;
1103 1105
1104 1106 /* List of features being negotated */
1105 1107 list_create(&dccp->dccp_features, sizeof (dccp_feature_t),
1106 1108 offsetof(dccp_feature_t, df_next));
1107 1109
1108 1110 connp->conn_recv = dccp_input_data;
1109 1111 connp->conn_recvicmp = dccp_icmp_input;
1110 1112 connp->conn_verifyicmp = dccp_verifyicmp;
1111 1113
1112 1114 connp->conn_ixa->ixa_notify = dccp_notify;
1113 1115 connp->conn_ixa->ixa_notify_cookie = dccp;
1114 1116
1115 1117 return ((void *)connp);
1116 1118 }
1117 1119
1118 1120 /*
1119 1121 * IPv4 connect.
1120 1122 */
1121 1123 static int
1122 1124 dccp_connect_ipv4(dccp_t *dccp, ipaddr_t *dstaddrp, in_port_t dstport,
1123 1125 uint_t srcid)
1124 1126 {
1125 1127 conn_t *connp = dccp->dccp_connp;
1126 1128 dccp_stack_t *dccps = dccp->dccp_dccps;
1127 1129 ipaddr_t dstaddr = *dstaddrp;
1128 1130 uint16_t lport;
1129 1131 int error;
1130 1132
1131 1133 cmn_err(CE_NOTE, "dccp.c: dccp_connect_ipv4");
1132 1134
1133 1135 ASSERT(connp->conn_ipversion == IPV4_VERSION);
1134 1136
1135 1137 if (dstaddr == INADDR_ANY) {
1136 1138 dstaddr = htonl(INADDR_LOOPBACK);
1137 1139 *dstaddrp = dstaddr;
1138 1140 }
1139 1141
1140 1142 /* Handle __sin6_src_id if socket not bound to an IP address */
1141 1143 if (srcid != 0 && connp->conn_laddr_v4 == INADDR_ANY) {
1142 1144 ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
1143 1145 IPCL_ZONEID(connp), dccps->dccps_netstack);
1144 1146 connp->conn_saddr_v6 = connp->conn_laddr_v6;
1145 1147 }
1146 1148
1147 1149 IN6_IPADDR_TO_V4MAPPED(dstaddr, &connp->conn_faddr_v6);
1148 1150 connp->conn_fport = dstport;
1149 1151
1150 1152 if (dccp->dccp_state == DCCPS_CLOSED) {
1151 1153 lport = dccp_update_next_port(dccps->dccps_next_port_to_try,
1152 1154 dccp, B_TRUE);
1153 1155 lport = dccp_bindi(dccp, lport, &connp->conn_laddr_v6, 0,
1154 1156 B_TRUE, B_FALSE, B_FALSE);
1155 1157 if (lport == 0) {
1156 1158 return (-TNOADDR);
1157 1159 }
1158 1160 }
1159 1161
1160 1162 error = dccp_set_destination(dccp);
1161 1163 if (error != 0) {
1162 1164 return (error);
1163 1165 }
1164 1166
1165 1167 /*
1166 1168 * Don't connect to oneself.
1167 1169 */
1168 1170 if (connp->conn_faddr_v4 == connp->conn_laddr_v4 &&
1169 1171 connp->conn_fport == connp->conn_lport) {
1170 1172 return (-TBADADDR);
1171 1173 }
1172 1174
1173 1175 dccp->dccp_state = DCCPS_REQUEST;
1174 1176
1175 1177 return (ipcl_conn_insert_v4(connp));
1176 1178 }
1177 1179
1178 1180 /*
1179 1181 * IPv6 connect.
1180 1182 */
1181 1183 static int
1182 1184 dccp_connect_ipv6(dccp_t *dccp, in6_addr_t *dstaddrp, in_port_t dstport,
1183 1185 uint32_t flowinfo, uint_t srcid, uint32_t scope_id)
1184 1186 {
1185 1187 cmn_err(CE_NOTE, "dccp.c: dccp_connect_ipv6");
1186 1188
1187 1189 return (0);
1188 1190 }
1189 1191
1190 1192 /*
1191 1193 * Set the ports via conn_connect and build the template
1192 1194 * header.
1193 1195 */
1194 1196 int
1195 1197 dccp_set_destination(dccp_t *dccp)
1196 1198 {
1197 1199 conn_t *connp = dccp->dccp_connp;
1198 1200 dccp_stack_t *dccps = dccp->dccp_dccps;
1199 1201 iulp_t uinfo;
1200 1202 uint32_t flags;
1201 1203 int error;
1202 1204
1203 1205 flags = IPDF_LSO | IPDF_ZCOPY;
1204 1206 flags |= IPDF_UNIQUE_DCE;
1205 1207
1206 1208 mutex_enter(&connp->conn_lock);
1207 1209 error = conn_connect(connp, &uinfo, flags);
1208 1210 mutex_exit(&connp->conn_lock);
1209 1211 if (error != 0) {
1210 1212 cmn_err(CE_NOTE, "conn_connect failed");
1211 1213 return (error);
1212 1214 }
1213 1215
1214 1216 error = dccp_build_hdrs(dccp);
1215 1217 if (error != 0) {
1216 1218 cmn_err(CE_NOTE, "dccp_build_hdrs failed");
1217 1219 return (error);
1218 1220 }
1219 1221
1220 1222 /* XXX */
1221 1223
1222 1224 /* Initialise the ISS */
1223 1225 dccp_iss_init(dccp);
1224 1226
1225 1227 mutex_enter(&connp->conn_lock);
1226 1228 connp->conn_state_flags &= ~CONN_INCIPIENT;
1227 1229 mutex_exit(&connp->conn_lock);
1228 1230
1229 1231 return (0);
1230 1232 }
1231 1233
1232 1234 /*
1233 1235 * Init the ISS.
1234 1236 */
1235 1237 static void
1236 1238 dccp_iss_init(dccp_t *dccp)
1237 1239 {
1238 1240 cmn_err(CE_NOTE, "dccp.c: dccp_iss_init");
1239 1241
1240 1242 dccp->dccp_iss += gethrtime();
1241 1243 dccp->dccp_gss = dccp->dccp_iss;
1242 1244 }
↓ open down ↓ |
927 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX