| 407 | } |
| 408 | |
| 409 | static int |
| 410 | ngd_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, |
| 411 | struct mbuf *control, struct thread *td) |
| 412 | { |
| 413 | struct epoch_tracker et; |
| 414 | struct ngpcb *const pcbp = sotongpcb(so); |
| 415 | struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr; |
| 416 | int len, error; |
| 417 | hook_p hook = NULL; |
| 418 | item_p item; |
| 419 | char hookname[NG_HOOKSIZ]; |
| 420 | |
| 421 | if ((pcbp == NULL) || (control != NULL)) { |
| 422 | error = EINVAL; |
| 423 | goto release; |
| 424 | } |
| 425 | if (pcbp->sockdata == NULL) { |
| 426 | error = ENOTCONN; |
| 427 | goto release; |
| 428 | } |
| 429 | |
| 430 | if (sap == NULL) |
| 431 | len = 0; /* Make compiler happy. */ |
| 432 | else |
| 433 | len = sap->sg_len - 2; |
| 434 | |
| 435 | /* |
| 436 | * If the user used any of these ways to not specify an address |
| 437 | * then handle specially. |
| 438 | */ |
| 439 | if ((sap == NULL) || (len <= 0) || (*sap->sg_data == '\0')) { |
| 440 | if (NG_NODE_NUMHOOKS(pcbp->sockdata->node) != 1) { |
| 441 | error = EDESTADDRREQ; |
| 442 | goto release; |
| 443 | } |
| 444 | /* |
| 445 | * If exactly one hook exists, just use it. |
| 446 | * Special case to allow write(2) to work on an ng_socket. |
| 447 | */ |
| 448 | hook = LIST_FIRST(&pcbp->sockdata->node->nd_hooks); |
| 449 | } else { |
| 450 | if (len >= NG_HOOKSIZ) { |
| 451 | error = EINVAL; |
| 452 | goto release; |
| 453 | } |
| 454 | |
| 455 | /* |
| 456 | * chop off the sockaddr header, and make sure it's NUL |
| 457 | * terminated |
| 458 | */ |
| 459 | bcopy(sap->sg_data, hookname, len); |
| 460 | hookname[len] = '\0'; |
| 461 | |
| 462 | /* Find the correct hook from 'hookname' */ |
| 463 | hook = ng_findhook(pcbp->sockdata->node, hookname); |
| 464 | if (hook == NULL) { |
| 465 | error = EHOSTUNREACH; |
| 466 | goto release; |
nothing calls this directly
no test coverage detected