| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* NOTICE: This is a clean room re-implementation of libnl */ |
| |
| #include <malloc.h> |
| #include "netlink-types.h" |
| #include "netlink/handlers.h" |
| |
| /* Allocate a new callback handle. */ |
| struct nl_cb *nl_cb_alloc(enum nl_cb_kind kind) |
| { |
| struct nl_cb *cb; |
| |
| cb = (struct nl_cb *) malloc(sizeof(struct nl_cb)); |
| if (cb == NULL) |
| goto fail; |
| memset(cb, 0, sizeof(*cb)); |
| |
| return nl_cb_get(cb); |
| fail: |
| return NULL; |
| } |
| |
| /* Clone an existing callback handle */ |
| struct nl_cb *nl_cb_clone(struct nl_cb *orig) |
| { |
| struct nl_cb *new_cb; |
| |
| new_cb = nl_cb_alloc(NL_CB_DEFAULT); |
| if (new_cb == NULL) |
| goto fail; |
| |
| /* Copy original and set refcount to 1 */ |
| memcpy(new_cb, orig, sizeof(*orig)); |
| new_cb->cb_refcnt = 1; |
| |
| return new_cb; |
| fail: |
| return NULL; |
| } |
| |
| /* Set up a callback. */ |
| int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind, \ |
| nl_recvmsg_msg_cb_t func, void *arg) |
| { |
| cb->cb_set[type] = func; |
| cb->cb_args[type] = arg; |
| return 0; |
| } |
| |
| |
| |
| /* Set up an error callback. */ |
| int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind, \ |
| nl_recvmsg_err_cb_t func, void *arg) |
| { |
| cb->cb_err = func; |
| cb->cb_err_arg = arg; |
| return 0; |
| |
| } |
| |
| struct nl_cb *nl_cb_get(struct nl_cb *cb) |
| { |
| cb->cb_refcnt++; |
| return cb; |
| } |
| |
| void nl_cb_put(struct nl_cb *cb) |
| { |
| if (!cb) |
| return; |
| cb->cb_refcnt--; |
| if (cb->cb_refcnt <= 0) |
| free(cb); |
| } |