1 /* $OpenBSD: log.c,v 1.3 2016/04/15 13:10:56 renato Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 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 <errno.h> 20 #include <stdarg.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <syslog.h> 25 #include <unistd.h> 26 #include <arpa/inet.h> 27 #include <netdb.h> 28 29 #include "eigrpd.h" 30 #include "rde.h" 31 #include "log.h" 32 33 static const char * const procnames[] = { 34 "parent", 35 "eigrpe", 36 "rde" 37 }; 38 39 int debug; 40 int verbose; 41 42 void 43 log_init(int n_debug) 44 { 45 extern char *__progname; 46 47 debug = n_debug; 48 49 if (!debug) 50 openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); 51 52 tzset(); 53 } 54 55 void 56 log_verbose(int v) 57 { 58 verbose = v; 59 } 60 61 void 62 logit(int pri, const char *fmt, ...) 63 { 64 va_list ap; 65 66 va_start(ap, fmt); 67 vlog(pri, fmt, ap); 68 va_end(ap); 69 } 70 71 void 72 vlog(int pri, const char *fmt, va_list ap) 73 { 74 char *nfmt; 75 76 if (debug) { 77 /* best effort in out of mem situations */ 78 if (asprintf(&nfmt, "%s\n", fmt) == -1) { 79 vfprintf(stderr, fmt, ap); 80 fprintf(stderr, "\n"); 81 } else { 82 vfprintf(stderr, nfmt, ap); 83 free(nfmt); 84 } 85 fflush(stderr); 86 } else 87 vsyslog(pri, fmt, ap); 88 } 89 90 void 91 log_warn(const char *emsg, ...) 92 { 93 char *nfmt; 94 va_list ap; 95 96 /* best effort to even work in out of memory situations */ 97 if (emsg == NULL) 98 logit(LOG_CRIT, "%s", strerror(errno)); 99 else { 100 va_start(ap, emsg); 101 102 if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) { 103 /* we tried it... */ 104 vlog(LOG_CRIT, emsg, ap); 105 logit(LOG_CRIT, "%s", strerror(errno)); 106 } else { 107 vlog(LOG_CRIT, nfmt, ap); 108 free(nfmt); 109 } 110 va_end(ap); 111 } 112 } 113 114 void 115 log_warnx(const char *emsg, ...) 116 { 117 va_list ap; 118 119 va_start(ap, emsg); 120 vlog(LOG_CRIT, emsg, ap); 121 va_end(ap); 122 } 123 124 void 125 log_info(const char *emsg, ...) 126 { 127 va_list ap; 128 129 va_start(ap, emsg); 130 vlog(LOG_INFO, emsg, ap); 131 va_end(ap); 132 } 133 134 void 135 log_debug(const char *emsg, ...) 136 { 137 va_list ap; 138 139 if (verbose) { 140 va_start(ap, emsg); 141 vlog(LOG_DEBUG, emsg, ap); 142 va_end(ap); 143 } 144 } 145 146 void 147 fatal(const char *emsg) 148 { 149 if (emsg == NULL) 150 logit(LOG_CRIT, "fatal in %s: %s", procnames[eigrpd_process], 151 strerror(errno)); 152 else 153 if (errno) 154 logit(LOG_CRIT, "fatal in %s: %s: %s", 155 procnames[eigrpd_process], emsg, strerror(errno)); 156 else 157 logit(LOG_CRIT, "fatal in %s: %s", 158 procnames[eigrpd_process], emsg); 159 160 if (eigrpd_process == PROC_MAIN) 161 exit(1); 162 else /* parent copes via SIGCHLD */ 163 _exit(1); 164 } 165 166 void 167 fatalx(const char *emsg) 168 { 169 errno = 0; 170 fatal(emsg); 171 } 172 173 #define NUM_LOGS 4 174 const char * 175 log_sockaddr(void *vp) 176 { 177 static char buf[NUM_LOGS][NI_MAXHOST]; 178 static int round = 0; 179 struct sockaddr *sa = vp; 180 181 round = (round + 1) % NUM_LOGS; 182 183 if (getnameinfo(sa, sa->sa_len, buf[round], NI_MAXHOST, NULL, 0, 184 NI_NUMERICHOST)) 185 return ("(unknown)"); 186 else 187 return (buf[round]); 188 } 189 190 const char * 191 log_in6addr(const struct in6_addr *addr) 192 { 193 struct sockaddr_in6 sa_in6; 194 195 memset(&sa_in6, 0, sizeof(sa_in6)); 196 sa_in6.sin6_len = sizeof(sa_in6); 197 sa_in6.sin6_family = AF_INET6; 198 sa_in6.sin6_addr = *addr; 199 200 recoverscope(&sa_in6); 201 202 return (log_sockaddr(&sa_in6)); 203 } 204 205 const char * 206 log_in6addr_scope(const struct in6_addr *addr, unsigned int ifindex) 207 { 208 struct sockaddr_in6 sa_in6; 209 210 memset(&sa_in6, 0, sizeof(sa_in6)); 211 sa_in6.sin6_len = sizeof(sa_in6); 212 sa_in6.sin6_family = AF_INET6; 213 sa_in6.sin6_addr = *addr; 214 215 addscope(&sa_in6, ifindex); 216 217 return (log_sockaddr(&sa_in6)); 218 } 219 220 const char * 221 log_addr(int af, union eigrpd_addr *addr) 222 { 223 static char buf[NUM_LOGS][INET6_ADDRSTRLEN]; 224 static int round = 0; 225 226 switch (af) { 227 case AF_INET: 228 round = (round + 1) % NUM_LOGS; 229 if (inet_ntop(AF_INET, &addr->v4, buf[round], 230 sizeof(buf[round])) == NULL) 231 return ("???"); 232 return (buf[round]); 233 case AF_INET6: 234 return (log_in6addr(&addr->v6)); 235 default: 236 break; 237 } 238 239 return ("???"); 240 } 241 242 const char * 243 log_prefix(struct rt_node *rn) 244 { 245 static char buf[64]; 246 247 if (snprintf(buf, sizeof(buf), "%s/%u", log_addr(rn->eigrp->af, 248 &rn->prefix), rn->prefixlen) == -1) 249 return ("???"); 250 251 return (buf); 252 } 253 254 const char * 255 log_route_origin(int af, struct rde_nbr *nbr) 256 { 257 if (nbr->flags & F_RDE_NBR_SELF) { 258 if (nbr->flags & F_RDE_NBR_REDIST) 259 return ("redistribute"); 260 if (nbr->flags & F_RDE_NBR_SUMMARY) 261 return ("summary"); 262 else 263 return ("connected"); 264 } 265 266 return (log_addr(af, &nbr->addr)); 267 } 268 269 const char * 270 opcode_name(uint8_t opcode) 271 { 272 switch (opcode) { 273 case EIGRP_OPC_UPDATE: 274 return ("UPDATE"); 275 case EIGRP_OPC_REQUEST: 276 return ("REQUEST"); 277 case EIGRP_OPC_QUERY: 278 return ("QUERY"); 279 case EIGRP_OPC_REPLY: 280 return ("REPLY"); 281 case EIGRP_OPC_HELLO: 282 return ("HELLO"); 283 case EIGRP_OPC_PROBE: 284 return ("PROBE"); 285 case EIGRP_OPC_SIAQUERY: 286 return ("SIAQUERY"); 287 case EIGRP_OPC_SIAREPLY: 288 return ("SIAREPLY"); 289 default: 290 return ("UNKNOWN"); 291 } 292 } 293 294 const char * 295 af_name(int af) 296 { 297 switch (af) { 298 case AF_INET: 299 return ("ipv4"); 300 case AF_INET6: 301 return ("ipv6"); 302 default: 303 return ("UNKNOWN"); 304 } 305 } 306 307 const char * 308 if_type_name(enum iface_type type) 309 { 310 switch (type) { 311 case IF_TYPE_POINTOPOINT: 312 return ("POINTOPOINT"); 313 case IF_TYPE_BROADCAST: 314 return ("BROADCAST"); 315 } 316 /* NOTREACHED */ 317 return ("UNKNOWN"); 318 } 319 320 const char * 321 dual_state_name(int state) 322 { 323 switch (state) { 324 case DUAL_STA_PASSIVE: 325 return ("PASSIVE"); 326 case DUAL_STA_ACTIVE0: 327 return ("ACTIVE(Oij=0)"); 328 case DUAL_STA_ACTIVE1: 329 return ("ACTIVE(Oij=1)"); 330 case DUAL_STA_ACTIVE2: 331 return ("ACTIVE(Oij=2)"); 332 case DUAL_STA_ACTIVE3: 333 return ("ACTIVE(Oij=3)"); 334 default: 335 return ("UNKNOWN"); 336 } 337 } 338 339 const char * 340 ext_proto_name(int proto) 341 { 342 switch (proto) { 343 case EIGRP_EXT_PROTO_IGRP: 344 return ("IGRP"); 345 case EIGRP_EXT_PROTO_EIGRP: 346 return ("EIGRP"); 347 case EIGRP_EXT_PROTO_STATIC: 348 return ("Static"); 349 case EIGRP_EXT_PROTO_RIP: 350 return ("RIP"); 351 case EIGRP_EXT_PROTO_HELLO: 352 return ("HELLO"); 353 case EIGRP_EXT_PROTO_OSPF: 354 return ("OSPF"); 355 case EIGRP_EXT_PROTO_ISIS: 356 return ("ISIS"); 357 case EIGRP_EXT_PROTO_EGP: 358 return ("EGP"); 359 case EIGRP_EXT_PROTO_BGP: 360 return ("BGP"); 361 case EIGRP_EXT_PROTO_IDRP: 362 return ("IDRP"); 363 case EIGRP_EXT_PROTO_CONN: 364 return ("Connected"); 365 default: 366 return ("UNKNOWN"); 367 } 368 } 369