1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 /* 17 * fork/exec a privileged helper to do the bind. 18 */ 19 20 #include <stdio.h> 21 #include <string.h> 22 #include <unistd.h> 23 #include <errno.h> 24 #include <sys/types.h> 25 #include <sys/wait.h> 26 #include <sys/socket.h> 27 #include <sys/note.h> 28 #include <netinet/in.h> 29 #include <arpa/inet.h> 30 31 int 32 ksocket_bind_helper(int fd, struct sockaddr *addr, uint_t addrlen) 33 { 34 char familystr[8]; 35 char portstr[12]; 36 char addrstr[INET6_ADDRSTRLEN]; 37 char *argv[6]; 38 const char *p; 39 /* LINTED E_BAD_PTR_CAST_ALIGN */ 40 struct sockaddr_in *sin = (struct sockaddr_in *)addr; 41 /* LINTED E_BAD_PTR_CAST_ALIGN */ 42 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 43 int pid, err, stat; 44 _NOTE(ARGUNUSED(addrlen)); 45 46 (void) snprintf(familystr, sizeof (familystr), "%d", addr->sa_family); 47 switch (addr->sa_family) { 48 case AF_INET: 49 (void) snprintf(portstr, sizeof (portstr), "%d", 50 ntohs(sin->sin_port)); 51 p = inet_ntop(AF_INET, &sin->sin_addr, 52 addrstr, sizeof (addrstr)); 53 break; 54 case AF_INET6: 55 (void) snprintf(portstr, sizeof (portstr), "%d", 56 ntohs(sin6->sin6_port)); 57 p = inet_ntop(AF_INET6, &sin6->sin6_addr, 58 addrstr, sizeof (addrstr)); 59 break; 60 default: 61 p = NULL; 62 break; 63 } 64 if (p == NULL) { 65 err = errno; 66 (void) fprintf(stdout, "ksocket_bind_helper, inet_ntop %s\n", 67 strerror(err)); 68 return (err); 69 } 70 71 (void) fprintf(stdout, "ksocket_bind_helper, " 72 "family=%s addr=%s port=%s\n", 73 familystr, addrstr, portstr); 74 75 argv[0] = "/usr/bin/pfexec"; 76 argv[1] = "/usr/lib/smbsrv/bind-helper"; 77 argv[2] = familystr; 78 argv[3] = addrstr; 79 argv[4] = portstr; 80 argv[5] = NULL; 81 82 pid = vfork(); 83 if (pid == -1) { 84 err = errno; 85 perror("fork"); 86 return (err); 87 } 88 if (pid == 0) { 89 (void) dup2(fd, 0); 90 (void) execv(argv[0], argv); 91 err = errno; 92 perror("execv"); 93 return (err); 94 } 95 err = waitpid(pid, &stat, 0); 96 if (err == -1) { 97 err = errno; 98 perror("waitpid"); 99 return (err); 100 } 101 if (WIFEXITED(stat)) { 102 err = WEXITSTATUS(stat); 103 if (err == 0) 104 return (0); 105 (void) fprintf(stderr, "helper exit %d\n", err); 106 } 107 return (EACCES); 108 } 109