1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Privilege Separation for dhcpcd, BSD driver 4 * Copyright (c) 2006-2020 Roy Marples <roy@marples.name> 5 * All rights reserved 6 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/ioctl.h> 30 31 #include <errno.h> 32 #include <unistd.h> 33 34 #include "dhcpcd.h" 35 #include "logerr.h" 36 #include "privsep.h" 37 38 static ssize_t 39 ps_root_doioctldom(int domain, unsigned long req, void *data, size_t len) 40 { 41 int s, err; 42 43 s = socket(domain, SOCK_DGRAM, 0); 44 if (s != -1) 45 err = ioctl(s, req, data, len); 46 else 47 err = -1; 48 if (s != -1) 49 close(s); 50 return err; 51 } 52 53 static ssize_t 54 ps_root_doroute(void *data, size_t len) 55 { 56 int s; 57 ssize_t err; 58 59 s = socket(PF_ROUTE, SOCK_RAW, 0); 60 if (s != -1) 61 err = write(s, data, len); 62 else 63 err = -1; 64 if (s != -1) 65 close(s); 66 return err; 67 } 68 69 ssize_t 70 ps_root_os(struct ps_msghdr *psm, struct msghdr *msg) 71 { 72 struct iovec *iov = msg->msg_iov; 73 void *data = iov->iov_base; 74 size_t len = iov->iov_len; 75 76 switch (psm->ps_cmd) { 77 case PS_IOCTLLINK: 78 return ps_root_doioctldom(PF_LINK, psm->ps_flags, data, len); 79 case PS_IOCTL6: 80 return ps_root_doioctldom(PF_INET6, psm->ps_flags, data, len); 81 case PS_ROUTE: 82 return ps_root_doroute(data, len); 83 default: 84 errno = ENOTSUP; 85 return -1; 86 } 87 } 88 89 static ssize_t 90 ps_root_ioctldom(struct dhcpcd_ctx *ctx, uint8_t domain, unsigned long request, 91 void *data, size_t len) 92 { 93 94 if (ps_sendcmd(ctx, ctx->ps_root_fd, domain, 95 request, data, len) == -1) 96 return -1; 97 return ps_root_readerror(ctx); 98 } 99 100 ssize_t 101 ps_root_ioctllink(struct dhcpcd_ctx *ctx, unsigned long request, 102 void *data,size_t len) 103 { 104 105 return ps_root_ioctldom(ctx, PS_IOCTLLINK, request, data, len); 106 } 107 108 ssize_t 109 ps_root_ioctl6(struct dhcpcd_ctx *ctx, unsigned long request, 110 void *data, size_t len) 111 { 112 113 return ps_root_ioctldom(ctx, PS_IOCTL6, request, data, len); 114 } 115 116 ssize_t 117 ps_root_route(struct dhcpcd_ctx *ctx, void *data, size_t len) 118 { 119 120 if (ps_sendcmd(ctx, ctx->ps_root_fd, PS_ROUTE, 0, data, len) == -1) 121 return -1; 122 return ps_root_readerror(ctx); 123 } 124