| 216 | } |
| 217 | |
| 218 | static int |
| 219 | ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, |
| 220 | struct mbuf *control, struct thread *td) |
| 221 | { |
| 222 | struct ngpcb *const pcbp = sotongpcb(so); |
| 223 | struct ngsock *const priv = NG_NODE_PRIVATE(pcbp->sockdata->node); |
| 224 | struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr; |
| 225 | struct ng_mesg *msg; |
| 226 | struct mbuf *m0; |
| 227 | item_p item; |
| 228 | char *path = NULL; |
| 229 | int len, error = 0; |
| 230 | struct ng_apply_info apply; |
| 231 | |
| 232 | if (control) { |
| 233 | error = EINVAL; |
| 234 | goto release; |
| 235 | } |
| 236 | |
| 237 | /* Require destination as there may be >= 1 hooks on this node. */ |
| 238 | if (addr == NULL) { |
| 239 | error = EDESTADDRREQ; |
| 240 | goto release; |
| 241 | } |
| 242 | |
| 243 | /* |
| 244 | * Allocate an expendable buffer for the path, chop off |
| 245 | * the sockaddr header, and make sure it's NUL terminated. |
| 246 | */ |
| 247 | len = sap->sg_len - 2; |
| 248 | path = malloc(len + 1, M_NETGRAPH_PATH, M_WAITOK); |
| 249 | bcopy(sap->sg_data, path, len); |
| 250 | path[len] = '\0'; |
| 251 | |
| 252 | /* |
| 253 | * Move the actual message out of mbufs into a linear buffer. |
| 254 | * Start by adding up the size of the data. (could use mh_len?) |
| 255 | */ |
| 256 | for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next) |
| 257 | len += m0->m_len; |
| 258 | |
| 259 | /* |
| 260 | * Move the data into a linear buffer as well. |
| 261 | * Messages are not delivered in mbufs. |
| 262 | */ |
| 263 | msg = malloc(len + 1, M_NETGRAPH_MSG, M_WAITOK); |
| 264 | m_copydata(m, 0, len, (char *)msg); |
| 265 | |
| 266 | if (msg->header.version != NG_VERSION) { |
| 267 | free(msg, M_NETGRAPH_MSG); |
| 268 | error = EINVAL; |
| 269 | goto release; |
| 270 | } |
| 271 | |
| 272 | /* |
| 273 | * Hack alert! |
| 274 | * We look into the message and if it mkpeers a node of unknown type, we |
| 275 | * try to load it. We need to do this now, in syscall thread, because if |
nothing calls this directly
no test coverage detected