|  | /* | 
|  | * 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); | 
|  | } |