libnl 1.1
|
00001 /* 00002 * lib/nl.c Core Netlink Interface 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @defgroup nl Core Netlink API 00014 * @brief 00015 * 00016 * @par Receiving Semantics 00017 * @code 00018 * nl_recvmsgs_default(socket) 00019 * | 00020 * | cb = nl_socket_get_cb(socket) 00021 * v 00022 * nl_recvmsgs(socket, cb) 00023 * | [Application provides nl_recvmsgs() replacement] 00024 * |- - - - - - - - - - - - - - - v 00025 * | cb->cb_recvmsgs_ow() 00026 * | 00027 * | [Application provides nl_recv() replacement] 00028 * +-------------->|- - - - - - - - - - - - - - - v 00029 * | nl_recv() cb->cb_recv_ow() 00030 * | +----------->|<- - - - - - - - - - - - - - -+ 00031 * | | v 00032 * | | Parse Message 00033 * | | |- - - - - - - - - - - - - - - v 00034 * | | | NL_CB_MSG_IN() 00035 * | | |<- - - - - - - - - - - - - - -+ 00036 * | | | 00037 * | | |- - - - - - - - - - - - - - - v 00038 * | | Sequence Check NL_CB_SEQ_CHECK() 00039 * | | |<- - - - - - - - - - - - - - -+ 00040 * | | | 00041 * | | |- - - - - - - - - - - - - - - v [ NLM_F_ACK is set ] 00042 * | | | NL_CB_SEND_ACK() 00043 * | | |<- - - - - - - - - - - - - - -+ 00044 * | | | 00045 * | | +-----+------+--------------+----------------+--------------+ 00046 * | | v v v v v 00047 * | | Valid Message ACK NOOP Message End of Multipart Error Message 00048 * | | | | | | | 00049 * | | v v v v v 00050 * | |NL_CB_VALID() NL_CB_ACK() NL_CB_SKIPPED() NL_CB_FINISH() cb->cb_err() 00051 * | | | | | | | 00052 * | | +------------+--------------+----------------+ v 00053 * | | | (FAILURE) 00054 * | | | [Callback returned NL_SKIP] 00055 * | | [More messages to be parsed] |<----------- 00056 * | +----------------------------------| 00057 * | | 00058 * | [Multipart message] | 00059 * +-------------------------------------| [Callback returned NL_STOP] 00060 * |<----------- 00061 * v 00062 * (SUCCESS) 00063 * 00064 * At any time: 00065 * Message Format Error 00066 * |- - - - - - - - - - - - v 00067 * v NL_CB_INVALID() 00068 * (FAILURE) 00069 * 00070 * Message Overrun (Kernel Lost Data) 00071 * |- - - - - - - - - - - - v 00072 * v NL_CB_OVERRUN() 00073 * (FAILURE) 00074 * 00075 * Callback returned negative error code 00076 * (FAILURE) 00077 * @endcode 00078 * 00079 * @par Sending Semantics 00080 * @code 00081 * nl_send_auto_complete() 00082 * | 00083 * | Automatically fill in PID and/or sequence number 00084 * | 00085 * | [Application provides nl_send() replacement] 00086 * |- - - - - - - - - - - - - - - - - - - - v 00087 * v cb->cb_send_ow() 00088 * nl_send() 00089 * | Add destination address and credentials 00090 * v 00091 * nl_sendmsg() 00092 * | Set source address 00093 * | 00094 * |- - - - - - - - - - - - - - - - - - - - v 00095 * | NL_CB_MSG_OUT() 00096 * |<- - - - - - - - - - - - - - - - - - - -+ 00097 * v 00098 * sendmsg() 00099 * @endcode 00100 * 00101 * @par 1) Connecting the socket 00102 * @code 00103 * // Bind and connect the socket to a protocol, NETLINK_ROUTE in this example. 00104 * nl_connect(handle, NETLINK_ROUTE); 00105 * @endcode 00106 * 00107 * @par 2) Sending data 00108 * @code 00109 * // The most rudimentary method is to use nl_sendto() simply pushing 00110 * // a piece of data to the other netlink peer. This method is not 00111 * // recommended. 00112 * const char buf[] = { 0x01, 0x02, 0x03, 0x04 }; 00113 * nl_sendto(handle, buf, sizeof(buf)); 00114 * 00115 * // A more comfortable interface is nl_send() taking a pointer to 00116 * // a netlink message. 00117 * struct nl_msg *msg = my_msg_builder(); 00118 * nl_send(handle, nlmsg_hdr(msg)); 00119 * 00120 * // nl_sendmsg() provides additional control over the sendmsg() message 00121 * // header in order to allow more specific addressing of multiple peers etc. 00122 * struct msghdr hdr = { ... }; 00123 * nl_sendmsg(handle, nlmsg_hdr(msg), &hdr); 00124 * 00125 * // You're probably too lazy to fill out the netlink pid, sequence number 00126 * // and message flags all the time. nl_send_auto_complete() automatically 00127 * // extends your message header as needed with an appropriate sequence 00128 * // number, the netlink pid stored in the netlink handle and the message 00129 * // flags NLM_F_REQUEST and NLM_F_ACK 00130 * nl_send_auto_complete(handle, nlmsg_hdr(msg)); 00131 * 00132 * // Simple protocols don't require the complex message construction interface 00133 * // and may favour nl_send_simple() to easly send a bunch of payload 00134 * // encapsulated in a netlink message header. 00135 * nl_send_simple(handle, MY_MSG_TYPE, 0, buf, sizeof(buf)); 00136 * @endcode 00137 * 00138 * @par 3) Receiving data 00139 * @code 00140 * // nl_recv() receives a single message allocating a buffer for the message 00141 * // content and gives back the pointer to you. 00142 * struct sockaddr_nl peer; 00143 * unsigned char *msg; 00144 * nl_recv(handle, &peer, &msg); 00145 * 00146 * // nl_recvmsgs() receives a bunch of messages until the callback system 00147 * // orders it to state, usually after receving a compolete multi part 00148 * // message series. 00149 * nl_recvmsgs(handle, my_callback_configuration); 00150 * 00151 * // nl_recvmsgs_default() acts just like nl_recvmsg() but uses the callback 00152 * // configuration stored in the handle. 00153 * nl_recvmsgs_default(handle); 00154 * 00155 * // In case you want to wait for the ACK to be recieved that you requested 00156 * // with your latest message, you can call nl_wait_for_ack() 00157 * nl_wait_for_ack(handle); 00158 * @endcode 00159 * 00160 * @par 4) Closing 00161 * @code 00162 * // Close the socket first to release kernel memory 00163 * nl_close(handle); 00164 * @endcode 00165 * 00166 * @{ 00167 */ 00168 00169 #include <netlink-local.h> 00170 #include <netlink/netlink.h> 00171 #include <netlink/utils.h> 00172 #include <netlink/handlers.h> 00173 #include <netlink/msg.h> 00174 #include <netlink/attr.h> 00175 00176 /** 00177 * @name Connection Management 00178 * @{ 00179 */ 00180 00181 /** 00182 * Create and connect netlink socket. 00183 * @arg handle Netlink handle. 00184 * @arg protocol Netlink protocol to use. 00185 * 00186 * Creates a netlink socket using the specified protocol, binds the socket 00187 * and issues a connection attempt. 00188 * 00189 * @return 0 on success or a negative error code. 00190 */ 00191 int nl_connect(struct nl_handle *handle, int protocol) 00192 { 00193 int err; 00194 socklen_t addrlen; 00195 00196 handle->h_fd = socket(AF_NETLINK, SOCK_RAW, protocol); 00197 if (handle->h_fd < 0) { 00198 err = nl_error(1, "socket(AF_NETLINK, ...) failed"); 00199 goto errout; 00200 } 00201 00202 if (!(handle->h_flags & NL_SOCK_BUFSIZE_SET)) { 00203 err = nl_set_buffer_size(handle, 0, 0); 00204 if (err < 0) 00205 goto errout; 00206 } 00207 00208 err = bind(handle->h_fd, (struct sockaddr*) &handle->h_local, 00209 sizeof(handle->h_local)); 00210 if (err < 0) { 00211 err = nl_error(1, "bind() failed"); 00212 goto errout; 00213 } 00214 00215 addrlen = sizeof(handle->h_local); 00216 err = getsockname(handle->h_fd, (struct sockaddr *) &handle->h_local, 00217 &addrlen); 00218 if (err < 0) { 00219 err = nl_error(1, "getsockname failed"); 00220 goto errout; 00221 } 00222 00223 if (addrlen != sizeof(handle->h_local)) { 00224 err = nl_error(EADDRNOTAVAIL, "Invalid address length"); 00225 goto errout; 00226 } 00227 00228 if (handle->h_local.nl_family != AF_NETLINK) { 00229 err = nl_error(EPFNOSUPPORT, "Address format not supported"); 00230 goto errout; 00231 } 00232 00233 handle->h_proto = protocol; 00234 00235 return 0; 00236 errout: 00237 close(handle->h_fd); 00238 handle->h_fd = -1; 00239 00240 return err; 00241 } 00242 00243 /** 00244 * Close/Disconnect netlink socket. 00245 * @arg handle Netlink handle 00246 */ 00247 void nl_close(struct nl_handle *handle) 00248 { 00249 if (handle->h_fd >= 0) { 00250 close(handle->h_fd); 00251 handle->h_fd = -1; 00252 } 00253 00254 handle->h_proto = 0; 00255 } 00256 00257 /** @} */ 00258 00259 /** 00260 * @name Send 00261 * @{ 00262 */ 00263 00264 /** 00265 * Send raw data over netlink socket. 00266 * @arg handle Netlink handle. 00267 * @arg buf Data buffer. 00268 * @arg size Size of data buffer. 00269 * @return Number of characters written on success or a negative error code. 00270 */ 00271 int nl_sendto(struct nl_handle *handle, void *buf, size_t size) 00272 { 00273 int ret; 00274 00275 ret = sendto(handle->h_fd, buf, size, 0, (struct sockaddr *) 00276 &handle->h_peer, sizeof(handle->h_peer)); 00277 if (ret < 0) 00278 return nl_errno(errno); 00279 00280 return ret; 00281 } 00282 00283 /** 00284 * Send netlink message with control over sendmsg() message header. 00285 * @arg handle Netlink handle. 00286 * @arg msg Netlink message to be sent. 00287 * @arg hdr Sendmsg() message header. 00288 * @return Number of characters sent on sucess or a negative error code. 00289 */ 00290 int nl_sendmsg(struct nl_handle *handle, struct nl_msg *msg, struct msghdr *hdr) 00291 { 00292 struct nl_cb *cb; 00293 int ret; 00294 00295 struct iovec iov = { 00296 .iov_base = (void *) nlmsg_hdr(msg), 00297 .iov_len = nlmsg_hdr(msg)->nlmsg_len, 00298 }; 00299 00300 hdr->msg_iov = &iov; 00301 hdr->msg_iovlen = 1; 00302 00303 nlmsg_set_src(msg, &handle->h_local); 00304 00305 cb = handle->h_cb; 00306 if (cb->cb_set[NL_CB_MSG_OUT]) 00307 if (nl_cb_call(cb, NL_CB_MSG_OUT, msg) != NL_OK) 00308 return 0; 00309 00310 ret = sendmsg(handle->h_fd, hdr, 0); 00311 if (ret < 0) 00312 return nl_errno(errno); 00313 00314 return ret; 00315 } 00316 00317 00318 /** 00319 * Send netlink message. 00320 * @arg handle Netlink handle 00321 * @arg msg Netlink message to be sent. 00322 * @see nl_sendmsg() 00323 * @return Number of characters sent on success or a negative error code. 00324 */ 00325 int nl_send(struct nl_handle *handle, struct nl_msg *msg) 00326 { 00327 struct sockaddr_nl *dst; 00328 struct ucred *creds; 00329 00330 struct msghdr hdr = { 00331 .msg_name = (void *) &handle->h_peer, 00332 .msg_namelen = sizeof(struct sockaddr_nl), 00333 }; 00334 00335 /* Overwrite destination if specified in the message itself, defaults 00336 * to the peer address of the handle. 00337 */ 00338 dst = nlmsg_get_dst(msg); 00339 if (dst->nl_family == AF_NETLINK) 00340 hdr.msg_name = dst; 00341 00342 /* Add credentials if present. */ 00343 creds = nlmsg_get_creds(msg); 00344 if (creds != NULL) { 00345 char buf[CMSG_SPACE(sizeof(struct ucred))]; 00346 struct cmsghdr *cmsg; 00347 00348 hdr.msg_control = buf; 00349 hdr.msg_controllen = sizeof(buf); 00350 00351 cmsg = CMSG_FIRSTHDR(&hdr); 00352 cmsg->cmsg_level = SOL_SOCKET; 00353 cmsg->cmsg_type = SCM_CREDENTIALS; 00354 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); 00355 memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred)); 00356 } 00357 00358 return nl_sendmsg(handle, msg, &hdr); 00359 } 00360 00361 /** 00362 * Send netlink message and check & extend header values as needed. 00363 * @arg handle Netlink handle. 00364 * @arg msg Netlink message to be sent. 00365 * 00366 * Checks the netlink message \c nlh for completness and extends it 00367 * as required before sending it out. Checked fields include pid, 00368 * sequence nr, and flags. 00369 * 00370 * @see nl_send() 00371 * @return Number of characters sent or a negative error code. 00372 */ 00373 int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg) 00374 { 00375 struct nlmsghdr *nlh; 00376 struct nl_cb *cb = handle->h_cb; 00377 00378 nlh = nlmsg_hdr(msg); 00379 if (nlh->nlmsg_pid == 0) 00380 nlh->nlmsg_pid = handle->h_local.nl_pid; 00381 00382 if (nlh->nlmsg_seq == 0) 00383 nlh->nlmsg_seq = handle->h_seq_next++; 00384 00385 if (msg->nm_protocol == -1) 00386 msg->nm_protocol = handle->h_proto; 00387 00388 nlh->nlmsg_flags |= (NLM_F_REQUEST | NLM_F_ACK); 00389 00390 if (cb->cb_send_ow) 00391 return cb->cb_send_ow(handle, msg); 00392 else 00393 return nl_send(handle, msg); 00394 } 00395 00396 /** 00397 * Send simple netlink message using nl_send_auto_complete() 00398 * @arg handle Netlink handle. 00399 * @arg type Netlink message type. 00400 * @arg flags Netlink message flags. 00401 * @arg buf Data buffer. 00402 * @arg size Size of data buffer. 00403 * 00404 * Builds a netlink message with the specified type and flags and 00405 * appends the specified data as payload to the message. 00406 * 00407 * @see nl_send_auto_complete() 00408 * @return Number of characters sent on success or a negative error code. 00409 */ 00410 int nl_send_simple(struct nl_handle *handle, int type, int flags, void *buf, 00411 size_t size) 00412 { 00413 int err; 00414 struct nl_msg *msg; 00415 00416 msg = nlmsg_alloc_simple(type, flags); 00417 if (!msg) 00418 return nl_errno(ENOMEM); 00419 00420 if (buf && size) { 00421 err = nlmsg_append(msg, buf, size, NLMSG_ALIGNTO); 00422 if (err < 0) 00423 goto errout; 00424 } 00425 00426 00427 err = nl_send_auto_complete(handle, msg); 00428 errout: 00429 nlmsg_free(msg); 00430 00431 return err; 00432 } 00433 00434 /** @} */ 00435 00436 /** 00437 * @name Receive 00438 * @{ 00439 */ 00440 00441 /** 00442 * Receive data from netlink socket 00443 * @arg handle Netlink handle. 00444 * @arg nla Destination pointer for peer's netlink address. 00445 * @arg buf Destination pointer for message content. 00446 * @arg creds Destination pointer for credentials. 00447 * 00448 * Receives a netlink message, allocates a buffer in \c *buf and 00449 * stores the message content. The peer's netlink address is stored 00450 * in \c *nla. The caller is responsible for freeing the buffer allocated 00451 * in \c *buf if a positive value is returned. Interruped system calls 00452 * are handled by repeating the read. The input buffer size is determined 00453 * by peeking before the actual read is done. 00454 * 00455 * A non-blocking sockets causes the function to return immediately with 00456 * a return value of 0 if no data is available. 00457 * 00458 * @return Number of octets read, 0 on EOF or a negative error code. 00459 */ 00460 int nl_recv(struct nl_handle *handle, struct sockaddr_nl *nla, 00461 unsigned char **buf, struct ucred **creds) 00462 { 00463 int n; 00464 int flags = 0; 00465 static int page_size = 0; 00466 struct iovec iov; 00467 struct msghdr msg = { 00468 .msg_name = (void *) nla, 00469 .msg_namelen = sizeof(struct sockaddr_nl), 00470 .msg_iov = &iov, 00471 .msg_iovlen = 1, 00472 .msg_control = NULL, 00473 .msg_controllen = 0, 00474 .msg_flags = 0, 00475 }; 00476 struct cmsghdr *cmsg; 00477 00478 if (handle->h_flags & NL_MSG_PEEK) 00479 flags |= MSG_PEEK; 00480 00481 if (page_size == 0) 00482 page_size = getpagesize(); 00483 00484 iov.iov_len = page_size; 00485 iov.iov_base = *buf = calloc(1, iov.iov_len); 00486 00487 if (handle->h_flags & NL_SOCK_PASSCRED) { 00488 msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); 00489 msg.msg_control = calloc(1, msg.msg_controllen); 00490 } 00491 retry: 00492 00493 n = recvmsg(handle->h_fd, &msg, flags); 00494 if (!n) 00495 goto abort; 00496 else if (n < 0) { 00497 if (errno == EINTR) { 00498 NL_DBG(3, "recvmsg() returned EINTR, retrying\n"); 00499 goto retry; 00500 } else if (errno == EAGAIN) { 00501 NL_DBG(3, "recvmsg() returned EAGAIN, aborting\n"); 00502 goto abort; 00503 } else { 00504 free(msg.msg_control); 00505 free(*buf); 00506 return nl_error(errno, "recvmsg failed"); 00507 } 00508 } 00509 00510 if (iov.iov_len < n || 00511 msg.msg_flags & MSG_TRUNC) { 00512 /* Provided buffer is not long enough, enlarge it 00513 * and try again. */ 00514 iov.iov_len *= 2; 00515 iov.iov_base = *buf = realloc(*buf, iov.iov_len); 00516 goto retry; 00517 } else if (msg.msg_flags & MSG_CTRUNC) { 00518 msg.msg_controllen *= 2; 00519 msg.msg_control = realloc(msg.msg_control, msg.msg_controllen); 00520 goto retry; 00521 } else if (flags != 0) { 00522 /* Buffer is big enough, do the actual reading */ 00523 flags = 0; 00524 goto retry; 00525 } 00526 00527 if (msg.msg_namelen != sizeof(struct sockaddr_nl)) { 00528 free(msg.msg_control); 00529 free(*buf); 00530 return nl_error(EADDRNOTAVAIL, "socket address size mismatch"); 00531 } 00532 00533 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 00534 if (cmsg->cmsg_level == SOL_SOCKET && 00535 cmsg->cmsg_type == SCM_CREDENTIALS) { 00536 *creds = calloc(1, sizeof(struct ucred)); 00537 memcpy(*creds, CMSG_DATA(cmsg), sizeof(struct ucred)); 00538 break; 00539 } 00540 } 00541 00542 free(msg.msg_control); 00543 return n; 00544 00545 abort: 00546 free(msg.msg_control); 00547 free(*buf); 00548 return 0; 00549 } 00550 00551 #define NL_CB_CALL(cb, type, msg) \ 00552 do { \ 00553 err = nl_cb_call(cb, type, msg); \ 00554 switch (err) { \ 00555 case NL_OK: \ 00556 err = 0; \ 00557 break; \ 00558 case NL_SKIP: \ 00559 goto skip; \ 00560 case NL_STOP: \ 00561 goto stop; \ 00562 default: \ 00563 goto out; \ 00564 } \ 00565 } while (0) 00566 00567 static int recvmsgs(struct nl_handle *handle, struct nl_cb *cb) 00568 { 00569 int n, err = 0, multipart = 0; 00570 unsigned char *buf = NULL; 00571 struct nlmsghdr *hdr; 00572 struct sockaddr_nl nla = {0}; 00573 struct nl_msg *msg = NULL; 00574 struct ucred *creds = NULL; 00575 00576 continue_reading: 00577 NL_DBG(3, "Attempting to read from %p\n", handle); 00578 if (cb->cb_recv_ow) 00579 n = cb->cb_recv_ow(handle, &nla, &buf, &creds); 00580 else 00581 n = nl_recv(handle, &nla, &buf, &creds); 00582 00583 if (n <= 0) 00584 return n; 00585 00586 NL_DBG(3, "recvmsgs(%p): Read %d bytes\n", handle, n); 00587 00588 hdr = (struct nlmsghdr *) buf; 00589 while (nlmsg_ok(hdr, n)) { 00590 NL_DBG(3, "recgmsgs(%p): Processing valid message...\n", 00591 handle); 00592 00593 nlmsg_free(msg); 00594 msg = nlmsg_convert(hdr); 00595 if (!msg) { 00596 err = nl_errno(ENOMEM); 00597 goto out; 00598 } 00599 00600 nlmsg_set_proto(msg, handle->h_proto); 00601 nlmsg_set_src(msg, &nla); 00602 if (creds) 00603 nlmsg_set_creds(msg, creds); 00604 00605 /* Raw callback is the first, it gives the most control 00606 * to the user and he can do his very own parsing. */ 00607 if (cb->cb_set[NL_CB_MSG_IN]) 00608 NL_CB_CALL(cb, NL_CB_MSG_IN, msg); 00609 00610 /* Sequence number checking. The check may be done by 00611 * the user, otherwise a very simple check is applied 00612 * enforcing strict ordering */ 00613 if (cb->cb_set[NL_CB_SEQ_CHECK]) 00614 NL_CB_CALL(cb, NL_CB_SEQ_CHECK, msg); 00615 else if (hdr->nlmsg_seq != handle->h_seq_expect) { 00616 if (cb->cb_set[NL_CB_INVALID]) 00617 NL_CB_CALL(cb, NL_CB_INVALID, msg); 00618 else { 00619 err = nl_error(EINVAL, 00620 "Sequence number mismatch"); 00621 goto out; 00622 } 00623 } 00624 00625 if (hdr->nlmsg_type == NLMSG_DONE || 00626 hdr->nlmsg_type == NLMSG_ERROR || 00627 hdr->nlmsg_type == NLMSG_NOOP || 00628 hdr->nlmsg_type == NLMSG_OVERRUN) { 00629 /* We can't check for !NLM_F_MULTI since some netlink 00630 * users in the kernel are broken. */ 00631 handle->h_seq_expect++; 00632 NL_DBG(3, "recvmsgs(%p): Increased expected " \ 00633 "sequence number to %d\n", 00634 handle, handle->h_seq_expect); 00635 } 00636 00637 if (hdr->nlmsg_flags & NLM_F_MULTI) 00638 multipart = 1; 00639 00640 /* Other side wishes to see an ack for this message */ 00641 if (hdr->nlmsg_flags & NLM_F_ACK) { 00642 if (cb->cb_set[NL_CB_SEND_ACK]) 00643 NL_CB_CALL(cb, NL_CB_SEND_ACK, msg); 00644 else { 00645 /* FIXME: implement */ 00646 } 00647 } 00648 00649 /* messages terminates a multpart message, this is 00650 * usually the end of a message and therefore we slip 00651 * out of the loop by default. the user may overrule 00652 * this action by skipping this packet. */ 00653 if (hdr->nlmsg_type == NLMSG_DONE) { 00654 multipart = 0; 00655 if (cb->cb_set[NL_CB_FINISH]) 00656 NL_CB_CALL(cb, NL_CB_FINISH, msg); 00657 } 00658 00659 /* Message to be ignored, the default action is to 00660 * skip this message if no callback is specified. The 00661 * user may overrule this action by returning 00662 * NL_PROCEED. */ 00663 else if (hdr->nlmsg_type == NLMSG_NOOP) { 00664 if (cb->cb_set[NL_CB_SKIPPED]) 00665 NL_CB_CALL(cb, NL_CB_SKIPPED, msg); 00666 else 00667 goto skip; 00668 } 00669 00670 /* Data got lost, report back to user. The default action is to 00671 * quit parsing. The user may overrule this action by retuning 00672 * NL_SKIP or NL_PROCEED (dangerous) */ 00673 else if (hdr->nlmsg_type == NLMSG_OVERRUN) { 00674 if (cb->cb_set[NL_CB_OVERRUN]) 00675 NL_CB_CALL(cb, NL_CB_OVERRUN, msg); 00676 else { 00677 err = nl_error(EOVERFLOW, "Overrun"); 00678 goto out; 00679 } 00680 } 00681 00682 /* Message carries a nlmsgerr */ 00683 else if (hdr->nlmsg_type == NLMSG_ERROR) { 00684 struct nlmsgerr *e = nlmsg_data(hdr); 00685 00686 if (hdr->nlmsg_len < nlmsg_msg_size(sizeof(*e))) { 00687 /* Truncated error message, the default action 00688 * is to stop parsing. The user may overrule 00689 * this action by returning NL_SKIP or 00690 * NL_PROCEED (dangerous) */ 00691 if (cb->cb_set[NL_CB_INVALID]) 00692 NL_CB_CALL(cb, NL_CB_INVALID, msg); 00693 else { 00694 err = nl_error(EINVAL, 00695 "Truncated error message"); 00696 goto out; 00697 } 00698 } else if (e->error) { 00699 /* Error message reported back from kernel. */ 00700 if (cb->cb_err) { 00701 err = cb->cb_err(&nla, e, 00702 cb->cb_err_arg); 00703 if (err < 0) 00704 goto out; 00705 else if (err == NL_SKIP) 00706 goto skip; 00707 else if (err == NL_STOP) { 00708 err = nl_error(-e->error, 00709 "Netlink Error"); 00710 goto out; 00711 } 00712 } else { 00713 err = nl_error(-e->error, 00714 "Netlink Error"); 00715 goto out; 00716 } 00717 } else if (cb->cb_set[NL_CB_ACK]) 00718 NL_CB_CALL(cb, NL_CB_ACK, msg); 00719 } else { 00720 /* Valid message (not checking for MULTIPART bit to 00721 * get along with broken kernels. NL_SKIP has no 00722 * effect on this. */ 00723 if (cb->cb_set[NL_CB_VALID]) 00724 NL_CB_CALL(cb, NL_CB_VALID, msg); 00725 } 00726 skip: 00727 err = 0; 00728 hdr = nlmsg_next(hdr, &n); 00729 } 00730 00731 nlmsg_free(msg); 00732 free(buf); 00733 free(creds); 00734 buf = NULL; 00735 msg = NULL; 00736 creds = NULL; 00737 00738 if (multipart) { 00739 /* Multipart message not yet complete, continue reading */ 00740 goto continue_reading; 00741 } 00742 stop: 00743 err = 0; 00744 out: 00745 nlmsg_free(msg); 00746 free(buf); 00747 free(creds); 00748 00749 return err; 00750 } 00751 00752 /** 00753 * Receive a set of messages from a netlink socket. 00754 * @arg handle netlink handle 00755 * @arg cb set of callbacks to control behaviour. 00756 * 00757 * Repeatedly calls nl_recv() or the respective replacement if provided 00758 * by the application (see nl_cb_overwrite_recv()) and parses the 00759 * received data as netlink messages. Stops reading if one of the 00760 * callbacks returns NL_STOP or nl_recv returns either 0 or a negative error code. 00761 * 00762 * A non-blocking sockets causes the function to return immediately if 00763 * no data is available. 00764 * 00765 * @return 0 on success or a negative error code from nl_recv(). 00766 */ 00767 int nl_recvmsgs(struct nl_handle *handle, struct nl_cb *cb) 00768 { 00769 if (cb->cb_recvmsgs_ow) 00770 return cb->cb_recvmsgs_ow(handle, cb); 00771 else 00772 return recvmsgs(handle, cb); 00773 } 00774 00775 /** 00776 * Receive a set of message from a netlink socket using handlers in nl_handle. 00777 * @arg handle netlink handle 00778 * 00779 * Calls nl_recvmsgs() with the handlers configured in the netlink handle. 00780 */ 00781 int nl_recvmsgs_default(struct nl_handle *handle) 00782 { 00783 return nl_recvmsgs(handle, handle->h_cb); 00784 00785 } 00786 00787 static int ack_wait_handler(struct nl_msg *msg, void *arg) 00788 { 00789 return NL_STOP; 00790 } 00791 00792 /** 00793 * Wait for ACK. 00794 * @arg handle netlink handle 00795 * @pre The netlink socket must be in blocking state. 00796 * 00797 * Waits until an ACK is received for the latest not yet acknowledged 00798 * netlink message. 00799 */ 00800 int nl_wait_for_ack(struct nl_handle *handle) 00801 { 00802 int err; 00803 struct nl_cb *cb; 00804 00805 cb = nl_cb_clone(handle->h_cb); 00806 if (cb == NULL) 00807 return nl_get_errno(); 00808 00809 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, NULL); 00810 err = nl_recvmsgs(handle, cb); 00811 nl_cb_put(cb); 00812 00813 return err; 00814 } 00815 00816 /** @} */ 00817 00818 /** @} */