1ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* 2ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * Copyright (C) 2011 The Android Open Source Project 3ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * 4ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * Licensed under the Apache License, Version 2.0 (the "License"); 5ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * you may not use this file except in compliance with the License. 6ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * You may obtain a copy of the License at 7ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * 8ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * http://www.apache.org/licenses/LICENSE-2.0 9ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * 10ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * Unless required by applicable law or agreed to in writing, software 11ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * distributed under the License is distributed on an "AS IS" BASIS, 12ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * See the License for the specific language governing permissions and 14ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * limitations under the License. 15ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker */ 16ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 17ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* NOTICE: This is a clean room re-implementation of libnl */ 18ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 19ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include <errno.h> 20ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include <unistd.h> 21ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include <malloc.h> 22ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include <sys/time.h> 23ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include <sys/socket.h> 24ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include "netlink-types.h" 25ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 26ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Join group */ 27ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nl_socket_add_membership(struct nl_sock *sk, int group) 28ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 29ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return setsockopt(sk->s_fd, SOL_NETLINK, 30ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); 31ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 32ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 33ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Allocate new netlink socket. */ 34d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidtstatic struct nl_sock *_nl_socket_alloc(void) 35ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 36c28b79a6c23226c1c24a2d8b954f7199195bba6fFrank Maker struct nl_sock *sk; 37ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct timeval tv; 38ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nl_cb *cb; 39ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 40c28b79a6c23226c1c24a2d8b954f7199195bba6fFrank Maker sk = (struct nl_sock *) malloc(sizeof(struct nl_sock)); 41ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (!sk) 42d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt return NULL; 43c28b79a6c23226c1c24a2d8b954f7199195bba6fFrank Maker memset(sk, 0, sizeof(*sk)); 44ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 45ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* Get current time */ 46ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 47ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (gettimeofday(&tv, NULL)) 48d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt goto fail; 49ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker else 50ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sk->s_seq_next = (int) tv.tv_sec; 51ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 52ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* Create local socket */ 53ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sk->s_local.nl_family = AF_NETLINK; 54c28b79a6c23226c1c24a2d8b954f7199195bba6fFrank Maker sk->s_local.nl_pid = 0; /* Kernel fills in pid */ 55ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sk->s_local.nl_groups = 0; /* No groups */ 56ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 57ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* Create peer socket */ 58ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sk->s_peer.nl_family = AF_NETLINK; 59ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sk->s_peer.nl_pid = 0; /* Kernel */ 60ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sk->s_peer.nl_groups = 0; /* No groups */ 61ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 62d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt return sk; 63d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidtfail: 64d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt free(sk); 65d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt return NULL; 66d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt} 67ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 68d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt/* Allocate new netlink socket. */ 69d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidtstruct nl_sock *nl_socket_alloc(void) 70d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt{ 71d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt struct nl_sock *sk = _nl_socket_alloc(); 72d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt struct nl_cb *cb; 73ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 74d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt if (!sk) 75d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt return NULL; 76d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt 77d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt cb = nl_cb_alloc(NL_CB_DEFAULT); 78d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt if (!cb) 79d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt goto cb_fail; 80d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt sk->s_cb = cb; 81ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return sk; 82ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makercb_fail: 83ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker free(sk); 84ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return NULL; 85ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 86ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 87ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Allocate new socket with custom callbacks. */ 88ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerstruct nl_sock *nl_socket_alloc_cb(struct nl_cb *cb) 89ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 90d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt struct nl_sock *sk = _nl_socket_alloc(); 91d99fe5ec960b5eae96585d5ceb59fe287fe0c5e7Dmitry Shmidt 92ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (!sk) 93c28b79a6c23226c1c24a2d8b954f7199195bba6fFrank Maker return NULL; 94ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 95ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sk->s_cb = cb; 96ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nl_cb_get(cb); 97ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 98ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return sk; 99ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 100ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 101ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Free a netlink socket. */ 102ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makervoid nl_socket_free(struct nl_sock *sk) 103ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 104ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nl_cb_put(sk->s_cb); 10569bc179b203c17380ba0b4fda7cf99af65cc5324Frank Maker close(sk->s_fd); 106ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker free(sk); 107ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 108ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 109ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Sets socket buffer size of netlink socket */ 110ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) 111ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 112ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF, \ 113ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker &rxbuf, (socklen_t) sizeof(rxbuf))) 114ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker goto error; 115ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 116ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF, \ 117ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker &txbuf, (socklen_t) sizeof(txbuf))) 118ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker goto error; 119ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 120ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return 0; 121ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makererror: 122ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return -errno; 123ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 124ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 125ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 126ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nl_socket_get_fd(struct nl_sock *sk) 127ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 128ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return sk->s_fd; 129ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 130de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt 131de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidtvoid nl_socket_set_cb(struct nl_sock *sk, struct nl_cb *cb) 132de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt{ 133de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt nl_cb_put(sk->s_cb); 134de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt sk->s_cb = cb; 135de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt nl_cb_get(cb); 136de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt} 137de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt 138de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidtstruct nl_cb *nl_socket_get_cb(struct nl_sock *sk) 139de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt{ 140de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt return nl_cb_get(sk->s_cb); 141de92239055ac87e51ef7e868ed9697d038a72368Dmitry Shmidt} 142