control.c revision 1.1
1/* $OpenBSD: control.c,v 1.1 2004/01/01 23:46:47 henning Exp $ */ 2 3/* 4 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/types.h> 20#include <sys/socket.h> 21#include <sys/un.h> 22#include <errno.h> 23#include <stdlib.h> 24#include <string.h> 25#include <unistd.h> 26 27#include "bgpd.h" 28#include "bgpdctl.h" 29#include "session.h" 30 31#define CONTROL_BACKLOG 5 32 33struct { 34 int fd; 35} control_state; 36 37struct ctl_conn *control_connbyfd(int); 38 39int 40control_init(void) 41{ 42 struct sockaddr_un sun; 43 int fd; 44 45 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 46 log_err("control_init: socket"); 47 return (-1); 48 } 49 50 bzero(&sun, sizeof(sun)); 51 sun.sun_family = AF_UNIX; 52 strlcpy(sun.sun_path, SOCKET_NAME, sizeof(sun.sun_path)); 53 if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { 54 log_err("control_init: bind: %s", SOCKET_NAME); 55 return (-1); 56 } 57 58 control_state.fd = fd; 59 60 return (fd); 61} 62 63int 64control_listen(void) 65{ 66 if (listen(control_state.fd, CONTROL_BACKLOG) == -1) { 67 log_err("control_listen: listen"); 68 return (-1); 69 } 70 71 return (control_state.fd); 72} 73 74void 75control_shutdown(void) 76{ 77 close(control_state.fd); 78} 79 80void 81control_cleanup(void) 82{ 83 unlink(SOCKET_NAME); 84} 85 86void 87control_accept(int listenfd) 88{ 89 int connfd; 90 socklen_t len; 91 struct sockaddr_un sun; 92 uid_t uid; 93 gid_t gid; 94 struct ctl_conn *ctl_conn; 95 96 len = sizeof(sun); 97 if ((connfd = accept(listenfd, 98 (struct sockaddr *)&sun, &len)) == -1) { 99 if (errno == EWOULDBLOCK || errno == EINTR) 100 return; 101 else 102 log_err("session_control_accept"); 103 } 104 105 if (getpeereid(connfd, &uid, &gid) == -1) { 106 log_err("session_control_accept"); 107 return; 108 } 109 110 if (uid) { 111 log_err("Connection to control socket with uid %ld", uid); 112 return; 113 } 114 115 if ((ctl_conn = malloc(sizeof(struct ctl_conn))) == NULL) { 116 log_err("session_control_accept"); 117 return; 118 } 119 120 imsg_init(&ctl_conn->ibuf, connfd); 121 122 TAILQ_INSERT_TAIL(&ctl_conns, ctl_conn, entries); 123} 124 125struct ctl_conn * 126control_connbyfd(int fd) 127{ 128 struct ctl_conn *c; 129 130 for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->ibuf.sock != fd; 131 c = TAILQ_NEXT(c, entries)) 132 ; /* nothing */ 133 134 return (c); 135} 136 137void 138control_close(int fd) 139{ 140 struct ctl_conn *c; 141 142 if ((c = control_connbyfd(fd)) == NULL) { 143 log_err("control_close: fd %d: not found", fd); 144 return; 145 } 146 147 TAILQ_REMOVE(&ctl_conns, c, entries); 148 149 close(c->ibuf.sock); 150 free(c); 151} 152 153int 154control_dispatch_msg(struct pollfd *pfd, int i) 155{ 156 struct imsg imsg; 157 struct ctl_conn *c; 158 int n; 159 struct peer *p; 160 161 if ((c = control_connbyfd(pfd->fd)) == NULL) { 162 log_err("control_dispatch_msg: fd %d: not found", pfd->fd); 163 return (0); 164 } 165 166 if (imsg_read(&c->ibuf) == -1) { 167 control_close(pfd->fd); 168 return (1); 169 } 170 171 for (;;) { 172 if ((n = imsg_get(&c->ibuf, &imsg)) == -1) { 173 control_close(pfd->fd); 174 return (1); 175 } 176 177 if (n == 0) 178 break; 179 180 switch (imsg.hdr.type) { 181 case IMSG_CTL_SHOW_NEIGHBOR: 182 for (p = conf->peers; p != NULL; p = p->next) 183 imsg_compose(&c->ibuf, IMSG_CTL_SHOW_NEIGHBOR, 184 0, p, sizeof(struct peer)); 185 break; 186 default: 187 break; 188 } 189 imsg_free(&imsg); 190 } 191 192 return (0); 193} 194