static void test_condition_test_host(void) { Condition *condition; sd_id128_t id; int r; char sid[SD_ID128_STRING_MAX]; _cleanup_free_ char *hostname = NULL; r = sd_id128_get_machine(&id); assert_se(r >= 0); assert_se(sd_id128_to_string(id, sid)); condition = condition_new(CONDITION_HOST, sid, false, false); assert_se(condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false); assert_se(!condition_test(condition)); condition_free(condition); condition = condition_new(CONDITION_HOST, sid, false, true); assert_se(!condition_test(condition)); condition_free(condition); hostname = gethostname_malloc(); assert_se(hostname); condition = condition_new(CONDITION_HOST, hostname, false, false); assert_se(condition_test(condition)); condition_free(condition); }
static int boot_info_new(struct boot_info **info) { struct boot_info *in; int err; in = new0(struct boot_info, 1); if (!in) return -ENOMEM; err = sd_id128_get_machine(&in->machine_id); if (err < 0) goto err; err = sd_id128_get_boot(&in->boot_id); if (err < 0) goto err; in->fw_entry_active = -1; in->loader_entry_active = -1; *info = in; return 0; err: free(in); return err; }
gboolean gl_util_can_read_user_journal (void) { GFile *file; GFileInfo *info; gint ret; gchar *path; gchar ids[33]; gchar *filename; gchar *uid; uid_t user_id; sd_id128_t machine; GError *error = NULL; GCredentials *credentials; credentials = g_credentials_new (); user_id = g_credentials_get_unix_user (credentials, &error); if (error != NULL) { g_debug ("Unable to get uid: %s", error->message); g_error_free (error); } uid = g_strdup_printf ("%d", user_id); filename = g_strconcat ("/user-", uid, ".journal", NULL); ret = sd_id128_get_machine (&machine); if (ret < 0) { g_critical ("Error getting machine id: %s", g_strerror (-ret)); } sd_id128_to_string (machine, ids); path = g_build_filename ("/var/log/journal", ids, filename, NULL); file = g_file_new_for_path (path); info = g_file_query_info (file, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_free (uid); g_free (path); g_free (filename); g_object_unref (file); g_object_unref (credentials); if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) { g_object_unref (info); return TRUE; } else { g_object_unref (info); return FALSE; } }
static void print_status_info(StatusInfo *i) { sd_id128_t mid, bid; int r; const char *id = NULL; _cleanup_free_ char *pretty_name = NULL, *cpe_name = NULL; struct utsname u; assert(i); printf(" Static hostname: %s\n", strna(i->static_hostname)); if (!isempty(i->pretty_hostname) && !streq_ptr(i->pretty_hostname, i->static_hostname)) printf(" Pretty hostname: %s\n", strna(i->pretty_hostname)); if (!isempty(i->hostname) && !streq_ptr(i->hostname, i->static_hostname)) printf("Transient hostname: %s\n", strna(i->hostname)); printf(" Icon name: %s\n" " Chassis: %s\n", strna(i->icon_name), strna(i->chassis)); r = sd_id128_get_machine(&mid); if (r >= 0) printf(" Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(mid)); r = sd_id128_get_boot(&bid); if (r >= 0) printf(" Boot ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(bid)); if (detect_virtualization(&id) > 0) printf(" Virtualization: %s\n", id); r = parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &pretty_name, "CPE_NAME", &cpe_name, NULL); if (!isempty(pretty_name)) printf(" Operating System: %s\n", pretty_name); if (!isempty(cpe_name)) printf(" CPE OS Name: %s\n", cpe_name); assert_se(uname(&u) >= 0); printf(" Kernel: %s %s\n" " Architecture: %s\n", u.sysname, u.release, u.machine); }
static void print_status_info(StatusInfo *i) { sd_id128_t mid = {}, bid = {}; int r; assert(i); printf(" Static hostname: %s\n", strna(i->static_hostname)); if (!isempty(i->pretty_hostname) && !streq_ptr(i->pretty_hostname, i->static_hostname)) printf(" Pretty hostname: %s\n", i->pretty_hostname); if (!isempty(i->hostname) && !streq_ptr(i->hostname, i->static_hostname)) printf("Transient hostname: %s\n", i->hostname); if (!isempty(i->icon_name)) printf(" Icon name: %s\n", strna(i->icon_name)); if (!isempty(i->chassis)) printf(" Chassis: %s\n", strna(i->chassis)); if (!isempty(i->deployment)) printf(" Deployment: %s\n", i->deployment); if (!isempty(i->location)) printf(" Location: %s\n", i->location); r = sd_id128_get_machine(&mid); if (r >= 0) printf(" Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(mid)); r = sd_id128_get_boot(&bid); if (r >= 0) printf(" Boot ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(bid)); if (!isempty(i->virtualization)) printf(" Virtualization: %s\n", i->virtualization); if (!isempty(i->os_pretty_name)) printf(" Operating System: %s\n", i->os_pretty_name); if (!isempty(i->os_cpe_name)) printf(" CPE OS Name: %s\n", i->os_cpe_name); if (!isempty(i->kernel_name) && !isempty(i->kernel_release)) printf(" Kernel: %s %s\n", i->kernel_name, i->kernel_release); if (!isempty(i->architecture)) printf(" Architecture: %s\n", i->architecture); }
gboolean gl_util_can_read_system_journal (GlJournalStorage storage_type) { GFile *file; GFileInfo *info; gint ret; gchar *path; gchar ids[33]; sd_id128_t machine; ret = sd_id128_get_machine (&machine); if (ret < 0) { g_critical ("Error getting machine id: %s", g_strerror (-ret)); } sd_id128_to_string (machine, ids); if (storage_type == GL_JOURNAL_STORAGE_PERSISTENT) { path = g_build_filename ("/var/log/journal", ids, "system.journal", NULL); } else if (storage_type == GL_JOURNAL_STORAGE_VOLATILE) { path = g_build_filename ("/run/log/journal", ids, "system.journal", NULL); } else { path = "/dev/null"; } file = g_file_new_for_path (path); info = g_file_query_info (file, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_free (path); g_object_unref (file); if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) { g_object_unref (info); return TRUE; } else { g_object_unref (info); return FALSE; } }
static int verb_machine_id(int argc, char **argv, void *userdata) { sd_id128_t id; int r; if (sd_id128_is_null(arg_app)) r = sd_id128_get_machine(&id); else r = sd_id128_get_machine_app_specific(arg_app, &id); if (r < 0) return log_error_errno(r, "Failed to get %smachine-ID: %m", sd_id128_is_null(arg_app) ? "" : "app-specific "); return id128_pretty_print(id, arg_pretty); }
int main(int argc, char *argv[]) { sd_id128_t id, id2; char t[33]; _cleanup_free_ char *b = NULL; assert_se(sd_id128_randomize(&id) == 0); printf("random: %s\n", sd_id128_to_string(id, t)); assert_se(sd_id128_from_string(t, &id2) == 0); assert_se(sd_id128_equal(id, id2)); if (sd_booted() > 0) { assert_se(sd_id128_get_machine(&id) == 0); printf("machine: %s\n", sd_id128_to_string(id, t)); assert_se(sd_id128_get_boot(&id) == 0); printf("boot: %s\n", sd_id128_to_string(id, t)); } printf("waldi: %s\n", sd_id128_to_string(ID128_WALDI, t)); assert_se(streq(t, STR_WALDI)); assert_se(asprintf(&b, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 32); printf("waldi2: %s\n", b); assert_se(streq(t, b)); assert_se(sd_id128_from_string(UUID_WALDI, &id) >= 0); assert_se(sd_id128_equal(id, ID128_WALDI)); assert_se(sd_id128_from_string("", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f101", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f10-", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a0b0c0d0e0f10", &id) < 0); assert_se(sd_id128_from_string("010203040506-0708-090a-0b0c0d0e0f10", &id) < 0); assert_se(id128_is_valid(STR_WALDI)); assert_se(id128_is_valid(UUID_WALDI)); assert_se(!id128_is_valid("")); assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f101")); assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f10-")); assert_se(!id128_is_valid("01020304-0506-0708-090a0b0c0d0e0f10")); assert_se(!id128_is_valid("010203040506-0708-090a-0b0c0d0e0f10")); return 0; }
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { sd_id128_t machine_id; int r; assert(duid); assert(len); r = sd_id128_get_machine(&machine_id); if (r < 0) return r; duid->type = htobe16(DHCP6_DUID_EN); duid->en.pen = htobe32(SYSTEMD_PEN); *len = sizeof(duid->type) + sizeof(duid->en); /* a bit of snake-oil perhaps, but no need to expose the machine-id directly */ siphash24(duid->en.id, &machine_id, sizeof(machine_id), HASH_KEY.bytes); return 0; }
gboolean gl_util_can_read_system_journal (void) { GFile *file; GFileInfo *info; gint ret; gchar *path; gchar ids[33]; sd_id128_t machine; ret = sd_id128_get_machine (&machine); if (ret < 0) { g_critical ("Error getting machine id: %s", g_strerror (-ret)); } sd_id128_to_string (machine, ids); path = g_build_filename ("/var/log/journal", ids, "system.journal", NULL); file = g_file_new_for_path (path); info = g_file_query_info (file, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_free (path); g_object_unref (file); if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) { g_object_unref (info); return TRUE; } else { g_object_unref (info); return FALSE; } }
static int manager_add_host_machine(Manager *m) { _cleanup_free_ char *rd = NULL, *unit = NULL; sd_id128_t mid; Machine *t; int r; if (m->host_machine) return 0; r = sd_id128_get_machine(&mid); if (r < 0) return log_error_errno(r, "Failed to get machine ID: %m"); rd = strdup("/"); if (!rd) return log_oom(); unit = strdup("-.slice"); if (!unit) return log_oom(); t = machine_new(m, MACHINE_HOST, ".host"); if (!t) return log_oom(); t->leader = 1; t->id = mid; t->root_directory = rd; t->unit = unit; rd = unit = NULL; dual_timestamp_from_boottime_or_monotonic(&t->timestamp, 0); m->host_machine = t; return 0; }
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { sd_id128_t machine_id; uint64_t hash; int r; assert(duid); assert(len); r = sd_id128_get_machine(&machine_id); if (r < 0) return r; unaligned_write_be16(&duid->type, DUID_TYPE_EN); unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN); *len = sizeof(duid->type) + sizeof(duid->en); /* a bit of snake-oil perhaps, but no need to expose the machine-id directly; duid->en.id might not be aligned, so we need to copy */ hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes)); memcpy(duid->en.id, &hash, sizeof(duid->en.id)); return 0; }
static int condition_test_host(Condition *c) { _cleanup_free_ char *h = NULL; sd_id128_t x, y; int r; assert(c); assert(c->parameter); assert(c->type == CONDITION_HOST); if (sd_id128_from_string(c->parameter, &x) >= 0) { r = sd_id128_get_machine(&y); if (r < 0) return r; return sd_id128_equal(x, y); } h = gethostname_malloc(); if (!h) return -ENOMEM; return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0; }
int main(int argc, char* argv[]) { #if 1 // For debug with segment fault struct sigaction sa; sa.sa_handler = backtrace_info; sigaction(SIGSEGV, &sa, NULL); // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); signal(SIGABRT, SIG_IGN); #endif int opt_g = 0; memset(&cltopt, 0, sizeof(CLT_OPT)); cltopt.C_TYPE = C_USR; while( (opt_g = getopt(argc, argv, "Dh")) != -1 ) { switch(opt_g) { case 'D': cltopt.C_TYPE = C_DAEMON; break; case 'h': default: usage(); exit(EXIT_SUCCESS); } } if(load_settings_client(&cltopt) == RET_NO) { st_d_error("加载配置文件settings.json出错!"); exit(EXIT_FAILURE); } OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); SSL_library_init(); //SSL_library_init() always returns "1" //int sd_id128_from_string(const char *s, sd_id128_t *ret); sd_id128_get_machine(&cltopt.mach_uuid); gethostname(cltopt.hostname, sizeof(cltopt.hostname)); st_d_print("CURRENT MACH_ID:%s, HOSTNAME:%s", SD_ID128_CONST_STR(cltopt.mach_uuid), cltopt.hostname); if (cltopt.C_TYPE == C_DAEMON) { cltopt.session_uuid = cltopt.mach_uuid; st_d_print("PLEASE REMEMEBER SET MACH_ID FOR USER TYPE!"); } dump_clt_opts(&cltopt); /*带配置产生event_base对象*/ struct event_config *cfg; cfg = event_config_new(); event_config_avoid_method(cfg, "select"); //避免使用select event_config_require_features(cfg, EV_FEATURE_ET); //使用边沿触发类型 base = event_base_new_with_config(cfg); event_config_free(cfg); st_d_print("当前复用Event模式: %s", event_base_get_method(base)); // epoll /*连接服务器*/ int srv_fd = socket(AF_INET, SOCK_STREAM, 0); unsigned int optval = 1; setsockopt(srv_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 if(sc_connect_srv(srv_fd) != RET_YES) { SYS_ABORT("连接服务器失败!"); } if(cltopt.C_TYPE == C_DAEMON) { if (sc_daemon_init_srv(srv_fd) != RET_YES) SYS_ABORT("(Daemon) 服务器返回错误!"); } else { if (sc_usr_init_srv(srv_fd) != RET_YES) SYS_ABORT("(Usr) 服务器返回错误!"); } st_d_print("客户端连接服务器OK!"); /** * USR 建立本地Listen侦听套接字 */ if (cltopt.C_TYPE == C_USR) { int i = 0; for (i=0; i<MAX_PORT_NUM; i++) { if (cltopt.maps[i].usrport) { struct evconnlistener *listener; struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0); sin.sin_port = htons(cltopt.maps[i].usrport); /* Port Num */ listener = evconnlistener_new_bind(base, accept_conn_cb, &cltopt.maps[i], LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1/*backlog 连接无限制*/, (struct sockaddr*)&sin, sizeof(sin)); if (!listener) { st_d_error("[USR]创建侦听套接字失败 %d:%d", cltopt.maps[i].usrport, cltopt.maps[i].daemonport); continue; } evconnlistener_set_error_cb(listener, accept_error_cb); st_d_print("[USR]创建侦听套接字 %d:%d OK", cltopt.maps[i].usrport, cltopt.maps[i].daemonport); } else break; } } encrypt_init(SD_ID128_CONST_STR(cltopt.mach_uuid), cltopt.enc_key); if (cltopt.C_TYPE == C_DAEMON && cltopt.ss5_port ) { /** * 目前只考虑将sockets5代理使用线程池来处理,其它的端口暴露 * 基本都是长连接,不单独处理 */ cltopt.thread_num = 5; cltopt.main_thread_id = pthread_self(); cltopt.thread_objs = (P_THREAD_OBJ)calloc(sizeof(THREAD_OBJ), cltopt.thread_num); if (!cltopt.thread_objs) { SYS_ABORT("申请THREAD_OBJ出错"); } sc_create_ss5_worker_threads(cltopt.thread_num, cltopt.thread_objs); st_d_print("[DAEMON]创建sockets5代理端口:%d", cltopt.ss5_port); struct evconnlistener *listener; struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0); sin.sin_port = htons(cltopt.ss5_port); /* Port Num */ listener = evconnlistener_new_bind(base, ss5_accept_conn_cb, NULL, LEV_OPT_LEAVE_SOCKETS_BLOCKING/* 阻塞 */|LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1/*backlog 连接无限制*/, (struct sockaddr*)&sin, sizeof(sin)); if (!listener) { st_d_error("[DAEMON]sockets5代理创建侦听套接字失败 %d", cltopt.ss5_port); exit(EXIT_FAILURE); } evconnlistener_set_error_cb(listener, accept_error_cb); st_d_print("[DAEMON]sockets5代理创建侦听套接字OK %d", cltopt.ss5_port); } if (cltopt.C_TYPE == C_DAEMON && cltopt.dns_port) { st_d_print("[DAEMON]创建DNS代理端口:%d", cltopt.dns_port); if (cltopt.dns_port != 53) { st_d_print("[DAEMON]请注意标准DNS侦听#53端口!"); } int dns_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (dns_socket < 0 ) { st_d_error("Create DNS socket error!"); exit(EXIT_FAILURE); } unsigned int optval = 1; setsockopt(dns_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法 setsockopt(dns_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); evutil_make_socket_closeonexec(dns_socket); evutil_make_socket_nonblocking(dns_socket); struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0); sin.sin_port = htons(cltopt.dns_port); /* Port Num */ if (bind(dns_socket, (struct sockaddr *)&sin, sizeof(sin))) { st_d_error("Bind DNS socket error!"); exit(EXIT_FAILURE); } cltopt.dns_transid_port_map = (unsigned short*)malloc(sizeof(unsigned short) * 0xFFFF); if (!cltopt.dns_transid_port_map) { st_d_error("Malloc for requestid-port failed!"); exit(EXIT_FAILURE); } P_PORTTRANS p_trans = sc_create_trans(cltopt.dns_port); if (!p_trans) { st_d_error("本地无空闲TRANS!"); exit(EXIT_FAILURE); } p_trans->is_enc = 1; p_trans->l_port = cltopt.dns_port; encrypt_ctx_init(&p_trans->ctx_enc, p_trans->l_port, cltopt.enc_key, 1); encrypt_ctx_init(&p_trans->ctx_dec, p_trans->l_port, cltopt.enc_key, 0); // 建立DNS UDP事件侦听 p_trans->extra_ev = event_new(base, dns_socket, EV_READ | EV_PERSIST, dns_client_to_proxy_cb, p_trans); int dns_srv_fd = socket(AF_INET, SOCK_STREAM, 0); if(sc_connect_srv(dns_srv_fd) != RET_YES) { SYS_ABORT("连接服务器失败!"); } sc_daemon_dns_init_srv(dns_srv_fd, p_trans->l_port, 12333); evutil_make_socket_nonblocking(dns_srv_fd); // later enabled //event_add(p_trans->extra_ev, NULL) != 0); p_trans->srv_bev = bufferevent_socket_new(base, dns_srv_fd, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(p_trans->srv_bev, dns_bufferread_cb_enc, NULL, dns_bufferevent_cb, p_trans); st_d_print("[DAEMON]DNS代理创建侦听套接字OK %d", cltopt.dns_port); } sc_set_eventcb_srv(srv_fd, base); /** * Main Loop Here */ event_base_loop(base, 0); event_base_free(base); st_d_print("程序退出!!!!"); return 0; }
int main(int argc, char *argv[]) { sd_id128_t id, id2; char t[33], q[37]; _cleanup_free_ char *b = NULL; _cleanup_close_ int fd = -1; assert_se(sd_id128_randomize(&id) == 0); printf("random: %s\n", sd_id128_to_string(id, t)); assert_se(sd_id128_from_string(t, &id2) == 0); assert_se(sd_id128_equal(id, id2)); if (sd_booted() > 0) { assert_se(sd_id128_get_machine(&id) == 0); printf("machine: %s\n", sd_id128_to_string(id, t)); assert_se(sd_id128_get_boot(&id) == 0); printf("boot: %s\n", sd_id128_to_string(id, t)); } printf("waldi: %s\n", sd_id128_to_string(ID128_WALDI, t)); assert_se(streq(t, STR_WALDI)); assert_se(asprintf(&b, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 32); printf("waldi2: %s\n", b); assert_se(streq(t, b)); printf("waldi3: %s\n", id128_to_uuid_string(ID128_WALDI, q)); assert_se(streq(q, UUID_WALDI)); b = mfree(b); assert_se(asprintf(&b, ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 36); printf("waldi4: %s\n", b); assert_se(streq(q, b)); assert_se(sd_id128_from_string(STR_WALDI, &id) >= 0); assert_se(sd_id128_equal(id, ID128_WALDI)); assert_se(sd_id128_from_string(UUID_WALDI, &id) >= 0); assert_se(sd_id128_equal(id, ID128_WALDI)); assert_se(sd_id128_from_string("", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f101", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f10-", &id) < 0); assert_se(sd_id128_from_string("01020304-0506-0708-090a0b0c0d0e0f10", &id) < 0); assert_se(sd_id128_from_string("010203040506-0708-090a-0b0c0d0e0f10", &id) < 0); assert_se(id128_is_valid(STR_WALDI)); assert_se(id128_is_valid(UUID_WALDI)); assert_se(!id128_is_valid("")); assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f101")); assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f10-")); assert_se(!id128_is_valid("01020304-0506-0708-090a0b0c0d0e0f10")); assert_se(!id128_is_valid("010203040506-0708-090a-0b0c0d0e0f10")); fd = open_tmpfile_unlinkable(NULL, O_RDWR|O_CLOEXEC); assert_se(fd >= 0); /* First, write as UUID */ assert_se(sd_id128_randomize(&id) >= 0); assert_se(id128_write_fd(fd, ID128_UUID, id, false) >= 0); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0); assert_se(sd_id128_equal(id, id2)); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0); assert_se(sd_id128_equal(id, id2)); /* Second, write as plain */ assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(ftruncate(fd, 0) >= 0); assert_se(sd_id128_randomize(&id) >= 0); assert_se(id128_write_fd(fd, ID128_PLAIN, id, false) >= 0); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0); assert_se(sd_id128_equal(id, id2)); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0); assert_se(sd_id128_equal(id, id2)); /* Third, write plain without trailing newline */ assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(ftruncate(fd, 0) >= 0); assert_se(sd_id128_randomize(&id) >= 0); assert_se(write(fd, sd_id128_to_string(id, t), 32) == 32); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0); assert_se(sd_id128_equal(id, id2)); /* Third, write UUID without trailing newline */ assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(ftruncate(fd, 0) >= 0); assert_se(sd_id128_randomize(&id) >= 0); assert_se(write(fd, id128_to_uuid_string(id, q), 36) == 36); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL); assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0); assert_se(sd_id128_equal(id, id2)); return 0; }
int main(int argc, char *argv[]) { _cleanup_close_ int seed_fd = -1, random_fd = -1; bool read_seed_file, write_seed_file; _cleanup_free_ void* buf = NULL; size_t buf_size = 0; struct stat st; ssize_t k; FILE *f; int r; if (argc != 2) { log_error("This program requires one argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_AUTO); log_parse_environment(); log_open(); umask(0022); /* Read pool size, if possible */ f = fopen("/proc/sys/kernel/random/poolsize", "re"); if (f) { if (fscanf(f, "%zu", &buf_size) > 0) /* poolsize is in bits on 2.6, but we want bytes */ buf_size /= 8; fclose(f); } if (buf_size < POOL_SIZE_MIN) buf_size = POOL_SIZE_MIN; r = mkdir_parents_label(RANDOM_SEED, 0755); if (r < 0) { log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m"); goto finish; } /* When we load the seed we read it and write it to the device and then immediately update the saved seed with * new data, to make sure the next boot gets seeded differently. */ if (streq(argv[1], "load")) { int open_rw_error; seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); open_rw_error = -errno; if (seed_fd < 0) { write_seed_file = false; seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (seed_fd < 0) { bool missing = errno == ENOENT; log_full_errno(missing ? LOG_DEBUG : LOG_ERR, open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m"); r = log_full_errno(missing ? LOG_DEBUG : LOG_ERR, errno, "Failed to open " RANDOM_SEED " for reading: %m"); if (missing) r = 0; goto finish; } } else write_seed_file = true; random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); if (random_fd < 0) { write_seed_file = false; random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600); if (random_fd < 0) { r = log_error_errno(errno, "Failed to open /dev/urandom: %m"); goto finish; } } read_seed_file = true; } else if (streq(argv[1], "save")) { random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (random_fd < 0) { r = log_error_errno(errno, "Failed to open /dev/urandom: %m"); goto finish; } seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); if (seed_fd < 0) { r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m"); goto finish; } read_seed_file = false; write_seed_file = true; } else { log_error("Unknown verb '%s'.", argv[1]); r = -EINVAL; goto finish; } if (fstat(seed_fd, &st) < 0) { r = log_error_errno(errno, "Failed to stat() seed file " RANDOM_SEED ": %m"); goto finish; } /* If the seed file is larger than what we expect, then honour the existing size and save/restore as much as it says */ if ((uint64_t) st.st_size > buf_size) buf_size = MIN(st.st_size, POOL_SIZE_MAX); buf = malloc(buf_size); if (!buf) { r = log_oom(); goto finish; } if (read_seed_file) { sd_id128_t mid; int z; k = loop_read(seed_fd, buf, buf_size, false); if (k < 0) r = log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m"); else if (k == 0) { r = 0; log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding."); } else { (void) lseek(seed_fd, 0, SEEK_SET); r = loop_write(random_fd, buf, (size_t) k, false); if (r < 0) log_error_errno(r, "Failed to write seed to /dev/urandom: %m"); } /* Let's also write the machine ID into the random seed. Why? As an extra protection against "golden * images" that are put together sloppily, i.e. images which are duplicated on multiple systems but * where the random seed file is not properly reset. Frequently the machine ID is properly reset on * those systems however (simply because it's easier to notice, if it isn't due to address clashes and * so on, while random seed equivalence is generally not noticed easily), hence let's simply write the * machined ID into the random pool too. */ z = sd_id128_get_machine(&mid); if (z < 0) log_debug_errno(z, "Failed to get machine ID, ignoring: %m"); else { z = loop_write(random_fd, &mid, sizeof(mid), false); if (z < 0) log_debug_errno(z, "Failed to write machine ID to /dev/urandom, ignoring: %m"); } } if (write_seed_file) { /* This is just a safety measure. Given that we are root and * most likely created the file ourselves the mode and owner * should be correct anyway. */ (void) fchmod(seed_fd, 0600); (void) fchown(seed_fd, 0, 0); k = loop_read(random_fd, buf, buf_size, false); if (k < 0) { r = log_error_errno(k, "Failed to read new seed from /dev/urandom: %m"); goto finish; } if (k == 0) { log_error("Got EOF while reading from /dev/urandom."); r = -EIO; goto finish; } r = loop_write(seed_fd, buf, (size_t) k, false); if (r < 0) log_error_errno(r, "Failed to write new random seed file: %m"); } finish: return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }
static int lldp_send_packet( int ifindex, const struct ether_addr *address, const void *packet, size_t packet_size) { union sockaddr_union sa = { .ll.sll_family = AF_PACKET, .ll.sll_protocol = htobe16(ETHERTYPE_LLDP), .ll.sll_ifindex = ifindex, .ll.sll_halen = ETH_ALEN, }; _cleanup_close_ int fd = -1; ssize_t l; assert(ifindex > 0); assert(address); assert(packet || packet_size <= 0); memcpy(sa.ll.sll_addr, address, ETH_ALEN); fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_RAW); if (fd < 0) return -errno; l = sendto(fd, packet, packet_size, MSG_NOSIGNAL, &sa.sa, sizeof(sa.ll)); if (l < 0) return -errno; if ((size_t) l != packet_size) return -EIO; return 0; } static int link_send_lldp(Link *link) { char machine_id_string[SD_ID128_STRING_MAX]; _cleanup_free_ char *hostname = NULL, *pretty_hostname = NULL; _cleanup_free_ void *packet = NULL; size_t packet_size = 0; sd_id128_t machine_id; uint16_t caps; usec_t ttl; int r; assert(link); if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) return 0; assert(link->network->lldp_emit < _LLDP_EMIT_MAX); r = sd_id128_get_machine(&machine_id); if (r < 0) return r; (void) gethostname_strict(&hostname); (void) parse_env_file("/etc/machine-info", NEWLINE, "PRETTY_HOSTNAME", &pretty_hostname, NULL); assert_cc(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1 <= (UINT16_MAX - 1) * USEC_PER_SEC); ttl = DIV_ROUND_UP(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1, USEC_PER_SEC); caps = (link->network && link->network->ip_forward != ADDRESS_FAMILY_NO) ? SD_LLDP_SYSTEM_CAPABILITIES_ROUTER : SD_LLDP_SYSTEM_CAPABILITIES_STATION; r = lldp_make_packet(link->network->lldp_emit, &link->mac, sd_id128_to_string(machine_id, machine_id_string), link->ifname, (uint16_t) ttl, link->network ? link->network->description : NULL, hostname, pretty_hostname, SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER, caps, &packet, &packet_size); if (r < 0) return r; return lldp_send_packet(link->ifindex, lldp_multicast_addr + link->network->lldp_emit, packet, packet_size); }
int journal_file_fss_load(JournalFile *f) { int r, fd = -1; char *p = NULL; struct stat st; FSSHeader *m = NULL; sd_id128_t machine; assert(f); if (!f->seal) return 0; r = sd_id128_get_machine(&machine); if (r < 0) return r; if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss", SD_ID128_FORMAT_VAL(machine)) < 0) return -ENOMEM; fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); if (fd < 0) { if (errno != ENOENT) log_error_errno(errno, "Failed to open %s: %m", p); r = -errno; goto finish; } if (fstat(fd, &st) < 0) { r = -errno; goto finish; } if (st.st_size < (off_t) sizeof(FSSHeader)) { r = -ENODATA; goto finish; } m = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0); if (m == MAP_FAILED) { m = NULL; r = -errno; goto finish; } if (memcmp(m->signature, FSS_HEADER_SIGNATURE, 8) != 0) { r = -EBADMSG; goto finish; } if (m->incompatible_flags != 0) { r = -EPROTONOSUPPORT; goto finish; } if (le64toh(m->header_size) < sizeof(FSSHeader)) { r = -EBADMSG; goto finish; } if (le64toh(m->fsprg_state_size) != FSPRG_stateinbytes(le16toh(m->fsprg_secpar))) { r = -EBADMSG; goto finish; } f->fss_file_size = le64toh(m->header_size) + le64toh(m->fsprg_state_size); if ((uint64_t) st.st_size < f->fss_file_size) { r = -ENODATA; goto finish; } if (!sd_id128_equal(machine, m->machine_id)) { r = -EHOSTDOWN; goto finish; } if (le64toh(m->start_usec) <= 0 || le64toh(m->interval_usec) <= 0) { r = -EBADMSG; goto finish; } f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (f->fss_file == MAP_FAILED) { f->fss_file = NULL; r = -errno; goto finish; } f->fss_start_usec = le64toh(f->fss_file->start_usec); f->fss_interval_usec = le64toh(f->fss_file->interval_usec); f->fsprg_state = (uint8_t*) f->fss_file + le64toh(f->fss_file->header_size); f->fsprg_state_size = le64toh(f->fss_file->fsprg_state_size); r = 0; finish: if (m) munmap(m, PAGE_ALIGN(sizeof(FSSHeader))); safe_close(fd); free(p); return r; }