• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ubus/ubusd_id.c

  1 /*
  2  * Copyright (C) 2011 Felix Fietkau <nbd@openwrt.org>
  3  *
  4  * This program is free software; you can redistribute it and/or modify
  5  * it under the terms of the GNU Lesser General Public License version 2.1
  6  * as published by the Free Software Foundation
  7  *
  8  * This program is distributed in the hope that it will be useful,
  9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 11  * GNU General Public License for more details.
 12  */
 13 
 14 #include <stdio.h>
 15 #include <stdlib.h>
 16 #include <unistd.h>
 17 #include <fcntl.h>
 18 #ifdef __linux__
 19 #include <sys/random.h>
 20 /* Added in Linux 5.6; define it in case the libc headers are older. */
 21 #ifndef GRND_INSECURE
 22 #define GRND_INSECURE 0x0004
 23 #endif
 24 #endif
 25 #include <libubox/avl-cmp.h>
 26 
 27 #include "ubusmsg.h"
 28 #include "ubusd_id.h"
 29 
 30 #ifndef __linux__
 31 static int random_fd = -1;
 32 #endif
 33 
 34 static ssize_t read_random(void *buf, size_t len)
 35 {
 36 #ifdef __linux__
 37         /*
 38          * IDs only need to be hard to guess, not crypto-strong.
 39          * GRND_INSECURE returns bytes without blocking on the CRNG, so
 40          * ubusd does not stall boot on boards whose pool seeds late.
 41          */
 42         return getrandom(buf, len, GRND_INSECURE);
 43 #else
 44         if (random_fd < 0) {
 45                 random_fd = open("/dev/urandom", O_RDONLY);
 46                 if (random_fd < 0) {
 47                         perror("open /dev/urandom");
 48                         return -1;
 49                 }
 50         }
 51         return read(random_fd, buf, len);
 52 #endif
 53 }
 54 
 55 static int ubus_cmp_id(const void *k1, const void *k2, void *ptr)
 56 {
 57         const uint32_t *id1 = k1, *id2 = k2;
 58 
 59         if (*id1 < *id2)
 60                 return -1;
 61         else
 62                 return *id1 > *id2;
 63 }
 64 
 65 void ubus_init_string_tree(struct avl_tree *tree, bool dup)
 66 {
 67         avl_init(tree, avl_strcmp, dup, NULL);
 68 }
 69 
 70 void ubus_init_id_tree(struct avl_tree *tree)
 71 {
 72         avl_init(tree, ubus_cmp_id, false, NULL);
 73 }
 74 
 75 bool ubus_alloc_id(struct avl_tree *tree, struct ubus_id *id, uint32_t val)
 76 {
 77         id->avl.key = &id->id;
 78         if (val) {
 79                 id->id = val;
 80                 return avl_insert(tree, &id->avl) == 0;
 81         }
 82 
 83         do {
 84                 do {
 85                         if (read_random(&id->id, sizeof(id->id)) != sizeof(id->id))
 86                                 return false;
 87                 } while (id->id < UBUS_SYSTEM_OBJECT_MAX);
 88         } while (avl_insert(tree, &id->avl) != 0);
 89 
 90         return true;
 91 }
 92 
 93 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt