Annotation of embedaddon/dnsmasq/contrib/lease-access/lease.access.patch, revision 1.1
1.1 ! misho 1: Index: src/dnsmasq.c
! 2: ===================================================================
! 3: --- src/dnsmasq.c (revision 696)
! 4: +++ src/dnsmasq.c (revision 821)
! 5: @@ -59,7 +59,6 @@
! 6: static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
! 7: static void check_dns_listeners(fd_set *set, time_t now);
! 8: static void sig_handler(int sig);
! 9: -static void async_event(int pipe, time_t now);
! 10: static void fatal_event(struct event_desc *ev);
! 11: static void poll_resolv(void);
! 12:
! 13: @@ -275,7 +274,7 @@
! 14: piperead = pipefd[0];
! 15: pipewrite = pipefd[1];
! 16: /* prime the pipe to load stuff first time. */
! 17: - send_event(pipewrite, EVENT_RELOAD, 0);
! 18: + send_event(pipewrite, EVENT_RELOAD, 0, 0);
! 19:
! 20: err_pipe[1] = -1;
! 21:
! 22: @@ -340,7 +339,7 @@
! 23: }
! 24: else if (getuid() == 0)
! 25: {
! 26: - send_event(err_pipe[1], EVENT_PIDFILE, errno);
! 27: + send_event(err_pipe[1], EVENT_PIDFILE, errno, 0);
! 28: _exit(0);
! 29: }
! 30: }
! 31: @@ -372,7 +371,7 @@
! 32: (setgroups(0, &dummy) == -1 ||
! 33: setgid(gp->gr_gid) == -1))
! 34: {
! 35: - send_event(err_pipe[1], EVENT_GROUP_ERR, errno);
! 36: + send_event(err_pipe[1], EVENT_GROUP_ERR, errno, 0);
! 37: _exit(0);
! 38: }
! 39:
! 40: @@ -415,14 +414,14 @@
! 41:
! 42: if (bad_capabilities != 0)
! 43: {
! 44: - send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities);
! 45: + send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, 0);
! 46: _exit(0);
! 47: }
! 48:
! 49: /* finally drop root */
! 50: if (setuid(ent_pw->pw_uid) == -1)
! 51: {
! 52: - send_event(err_pipe[1], EVENT_USER_ERR, errno);
! 53: + send_event(err_pipe[1], EVENT_USER_ERR, errno, 0);
! 54: _exit(0);
! 55: }
! 56:
! 57: @@ -434,7 +433,7 @@
! 58: /* lose the setuid and setgid capbilities */
! 59: if (capset(hdr, data) == -1)
! 60: {
! 61: - send_event(err_pipe[1], EVENT_CAP_ERR, errno);
! 62: + send_event(err_pipe[1], EVENT_CAP_ERR, errno, 0);
! 63: _exit(0);
! 64: }
! 65: #endif
! 66: @@ -647,7 +646,7 @@
! 67: }
! 68:
! 69: if (FD_ISSET(piperead, &rset))
! 70: - async_event(piperead, now);
! 71: + async_event(piperead, now, NULL, 0);
! 72:
! 73: #ifdef HAVE_LINUX_NETWORK
! 74: if (FD_ISSET(daemon->netlinkfd, &rset))
! 75: @@ -674,7 +673,7 @@
! 76: #endif
! 77:
! 78: if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
! 79: - dhcp_packet(now);
! 80: + dhcp_packet(piperead, now);
! 81:
! 82: #ifndef NO_FORK
! 83: if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
! 84: @@ -719,17 +718,18 @@
! 85: else
! 86: return;
! 87:
! 88: - send_event(pipewrite, event, 0);
! 89: + send_event(pipewrite, event, 0, 0);
! 90: errno = errsave;
! 91: }
! 92: }
! 93:
! 94: -void send_event(int fd, int event, int data)
! 95: +void send_event(int fd, int event, int data, int priv)
! 96: {
! 97: struct event_desc ev;
! 98:
! 99: ev.event = event;
! 100: ev.data = data;
! 101: + ev.priv = priv;
! 102:
! 103: /* error pipe, debug mode. */
! 104: if (fd == -1)
! 105: @@ -771,14 +771,17 @@
! 106: die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE);
! 107: }
! 108: }
! 109: -
! 110: -static void async_event(int pipe, time_t now)
! 111: +
! 112: +/* returns the private data of the event
! 113: + */
! 114: +int async_event(int pipe, time_t now, struct event_desc* event, unsigned int secs)
! 115: {
! 116: pid_t p;
! 117: struct event_desc ev;
! 118: int i;
! 119:
! 120: - if (read_write(pipe, (unsigned char *)&ev, sizeof(ev), 1))
! 121: + if (read_timeout(pipe, (unsigned char *)&ev, sizeof(ev), now, secs) > 0)
! 122: + {
! 123: switch (ev.event)
! 124: {
! 125: case EVENT_RELOAD:
! 126: @@ -872,6 +875,14 @@
! 127: flush_log();
! 128: exit(EC_GOOD);
! 129: }
! 130: + }
! 131: + else
! 132: + return -1; /* timeout */
! 133: +
! 134: + if (event)
! 135: + memcpy( event, &ev, sizeof(ev));
! 136: +
! 137: + return 0;
! 138: }
! 139:
! 140: static void poll_resolv()
! 141: Index: src/config.h
! 142: ===================================================================
! 143: --- src/config.h (revision 696)
! 144: +++ src/config.h (revision 821)
! 145: @@ -51,6 +51,8 @@
! 146: #define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
! 147: #define LOG_MAX 5 /* log-queue length */
! 148: #define RANDFILE "/dev/urandom"
! 149: +#define SCRIPT_TIMEOUT 6
! 150: +#define LEASE_CHECK_TIMEOUT 10
! 151:
! 152: /* DBUS interface specifics */
! 153: #define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
! 154: Index: src/dnsmasq.h
! 155: ===================================================================
! 156: --- src/dnsmasq.h (revision 696)
! 157: +++ src/dnsmasq.h (revision 821)
! 158: @@ -116,6 +116,7 @@
! 159: /* Async event queue */
! 160: struct event_desc {
! 161: int event, data;
! 162: + unsigned int priv;
! 163: };
! 164:
! 165: #define EVENT_RELOAD 1
! 166: @@ -390,6 +391,7 @@
! 167: #define ACTION_OLD_HOSTNAME 2
! 168: #define ACTION_OLD 3
! 169: #define ACTION_ADD 4
! 170: +#define ACTION_ACCESS 5
! 171:
! 172: #define DHCP_CHADDR_MAX 16
! 173:
! 174: @@ -709,6 +711,7 @@
! 175: char *print_mac(char *buff, unsigned char *mac, int len);
! 176: void bump_maxfd(int fd, int *max);
! 177: int read_write(int fd, unsigned char *packet, int size, int rw);
! 178: +int read_timeout(int fd, unsigned char *packet, int size, time_t now, int secs);
! 179:
! 180: /* log.c */
! 181: void die(char *message, char *arg1, int exit_code);
! 182: @@ -748,7 +751,7 @@
! 183:
! 184: /* dhcp.c */
! 185: void dhcp_init(void);
! 186: -void dhcp_packet(time_t now);
! 187: +void dhcp_packet(int piperead, time_t now);
! 188:
! 189: struct dhcp_context *address_available(struct dhcp_context *context,
! 190: struct in_addr addr,
! 191: @@ -792,14 +795,16 @@
! 192: void rerun_scripts(void);
! 193:
! 194: /* rfc2131.c */
! 195: -size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
! 196: +size_t dhcp_reply(int pipefd, struct dhcp_context *context, char *iface_name, int int_index,
! 197: size_t sz, time_t now, int unicast_dest, int *is_inform);
! 198:
! 199: /* dnsmasq.c */
! 200: int make_icmp_sock(void);
! 201: int icmp_ping(struct in_addr addr);
! 202: -void send_event(int fd, int event, int data);
! 203: +void send_event(int fd, int event, int data, int priv);
! 204: void clear_cache_and_reload(time_t now);
! 205: +int wait_for_child(int pipe);
! 206: +int async_event(int pipe, time_t now, struct event_desc*, unsigned int timeout);
! 207:
! 208: /* isc.c */
! 209: #ifdef HAVE_ISC_READER
! 210: @@ -832,9 +837,9 @@
! 211: /* helper.c */
! 212: #ifndef NO_FORK
! 213: int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
! 214: -void helper_write(void);
! 215: +int helper_write(void);
! 216: void queue_script(int action, struct dhcp_lease *lease,
! 217: - char *hostname, time_t now);
! 218: + char *hostname, time_t now, unsigned int uid);
! 219: int helper_buf_empty(void);
! 220: #endif
! 221:
! 222: Index: src/util.c
! 223: ===================================================================
! 224: --- src/util.c (revision 696)
! 225: +++ src/util.c (revision 821)
! 226: @@ -444,3 +444,38 @@
! 227: return 1;
! 228: }
! 229:
! 230: +int read_timeout(int fd, unsigned char *packet, int size, time_t now, int secs)
! 231: +{
! 232: + ssize_t n, done;
! 233: + time_t expire;
! 234: +
! 235: + expire = now + secs;
! 236: +
! 237: + for (done = 0; done < size; done += n)
! 238: + {
! 239: + retry:
! 240: + if (secs > 0) alarm(secs);
! 241: + n = read(fd, &packet[done], (size_t)(size - done));
! 242: +
! 243: + if (n == 0)
! 244: + return 0;
! 245: + else if (n == -1)
! 246: + {
! 247: + if (errno == EINTR) {
! 248: + my_syslog(LOG_INFO, _("read timed out (errno %d)"), errno);
! 249: + return 0;
! 250: + }
! 251: +
! 252: + if (retry_send() || errno == ENOMEM || errno == ENOBUFS || errno == EAGAIN)
! 253: + {
! 254: + if (secs == 0 || (secs > 0 && dnsmasq_time() < expire))
! 255: + goto retry;
! 256: + }
! 257: +
! 258: + my_syslog(LOG_INFO, _("error in read (timeout %d, errno %d)"), secs, errno);
! 259: + return 0;
! 260: + }
! 261: + }
! 262: + return 1;
! 263: +}
! 264: +
! 265: Index: src/dhcp.c
! 266: ===================================================================
! 267: --- src/dhcp.c (revision 696)
! 268: +++ src/dhcp.c (revision 821)
! 269: @@ -103,7 +103,7 @@
! 270: daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
! 271: }
! 272:
! 273: -void dhcp_packet(time_t now)
! 274: +void dhcp_packet(int piperead, time_t now)
! 275: {
! 276: struct dhcp_packet *mess;
! 277: struct dhcp_context *context;
! 278: @@ -239,7 +239,8 @@
! 279: if (!iface_enumerate(&parm, complete_context, NULL))
! 280: return;
! 281: lease_prune(NULL, now); /* lose any expired leases */
! 282: - iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
! 283: +
! 284: + iov.iov_len = dhcp_reply(piperead, parm.current, ifr.ifr_name, iface_index, (size_t)sz,
! 285: now, unicast_dest, &is_inform);
! 286: lease_update_file(now);
! 287: lease_update_dns();
! 288: Index: src/helper.c
! 289: ===================================================================
! 290: --- src/helper.c (revision 696)
! 291: +++ src/helper.c (revision 821)
! 292: @@ -45,6 +45,7 @@
! 293: #endif
! 294: unsigned char hwaddr[DHCP_CHADDR_MAX];
! 295: char interface[IF_NAMESIZE];
! 296: + unsigned int uid;
! 297: };
! 298:
! 299: static struct script_data *buf = NULL;
! 300: @@ -60,7 +61,7 @@
! 301: then fork our process. */
! 302: if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
! 303: {
! 304: - send_event(err_fd, EVENT_PIPE_ERR, errno);
! 305: + send_event(err_fd, EVENT_PIPE_ERR, errno, 0);
! 306: _exit(0);
! 307: }
! 308:
! 309: @@ -87,13 +88,13 @@
! 310: {
! 311: if (daemon->options & OPT_NO_FORK)
! 312: /* send error to daemon process if no-fork */
! 313: - send_event(event_fd, EVENT_HUSER_ERR, errno);
! 314: + send_event(event_fd, EVENT_HUSER_ERR, errno, 0);
! 315: else
! 316: {
! 317: /* kill daemon */
! 318: - send_event(event_fd, EVENT_DIE, 0);
! 319: + send_event(event_fd, EVENT_DIE, 0, 0);
! 320: /* return error */
! 321: - send_event(err_fd, EVENT_HUSER_ERR, errno);;
! 322: + send_event(err_fd, EVENT_HUSER_ERR, errno, 0);
! 323: }
! 324: _exit(0);
! 325: }
! 326: @@ -122,6 +123,8 @@
! 327: action_str = "del";
! 328: else if (data.action == ACTION_ADD)
! 329: action_str = "add";
! 330: + else if (data.action == ACTION_ACCESS)
! 331: + action_str = "access";
! 332: else if (data.action == ACTION_OLD || data.action == ACTION_OLD_HOSTNAME)
! 333: action_str = "old";
! 334: else
! 335: @@ -178,9 +181,11 @@
! 336: {
! 337: /* On error send event back to main process for logging */
! 338: if (WIFSIGNALED(status))
! 339: - send_event(event_fd, EVENT_KILLED, WTERMSIG(status));
! 340: - else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
! 341: - send_event(event_fd, EVENT_EXITED, WEXITSTATUS(status));
! 342: + send_event(event_fd, EVENT_KILLED, WTERMSIG(status), data.uid);
! 343: + else if (WIFEXITED(status))
! 344: + send_event(event_fd, EVENT_EXITED, WEXITSTATUS(status), data.uid);
! 345: + else
! 346: + send_event(event_fd, EVENT_EXITED, -1, data.uid);
! 347: break;
! 348: }
! 349:
! 350: @@ -263,7 +268,7 @@
! 351: err = errno;
! 352: }
! 353: /* failed, send event so the main process logs the problem */
! 354: - send_event(event_fd, EVENT_EXEC_ERR, err);
! 355: + send_event(event_fd, EVENT_EXEC_ERR, err, data.uid);
! 356: _exit(0);
! 357: }
! 358: }
! 359: @@ -295,7 +300,7 @@
! 360: }
! 361:
! 362: /* pack up lease data into a buffer */
! 363: -void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now)
! 364: +void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now, unsigned int uid)
! 365: {
! 366: unsigned char *p;
! 367: size_t size;
! 368: @@ -332,6 +337,7 @@
! 369: buf_size = size;
! 370: }
! 371:
! 372: + buf->uid = uid;
! 373: buf->action = action;
! 374: buf->hwaddr_len = lease->hwaddr_len;
! 375: buf->hwaddr_type = lease->hwaddr_type;
! 376: @@ -393,12 +399,15 @@
! 377: return bytes_in_buf == 0;
! 378: }
! 379:
! 380: -void helper_write(void)
! 381: +/* returns -1 if write failed for a reason, 1 if no data exist
! 382: + * and 0 if everything was ok.
! 383: + */
! 384: +int helper_write(void)
! 385: {
! 386: ssize_t rc;
! 387:
! 388: if (bytes_in_buf == 0)
! 389: - return;
! 390: + return 1;
! 391:
! 392: if ((rc = write(daemon->helperfd, buf, bytes_in_buf)) != -1)
! 393: {
! 394: @@ -409,9 +418,11 @@
! 395: else
! 396: {
! 397: if (errno == EAGAIN || errno == EINTR)
! 398: - return;
! 399: + return -1;
! 400: bytes_in_buf = 0;
! 401: }
! 402: +
! 403: + return 0;
! 404: }
! 405:
! 406: #endif
! 407: Index: src/rfc2131.c
! 408: ===================================================================
! 409: --- src/rfc2131.c (revision 696)
! 410: +++ src/rfc2131.c (revision 821)
! 411: @@ -100,8 +100,49 @@
! 412: int clid_len, unsigned char *clid, int *len_out);
! 413: static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
! 414:
! 415: +static int check_access_script( int piperead, struct dhcp_lease *lease, struct dhcp_packet *mess, time_t now)
! 416: +{
! 417: +#ifndef NO_FORK
! 418: +unsigned int uid;
! 419: +struct event_desc ev;
! 420: +int ret;
! 421: +struct dhcp_lease _lease;
! 422: +
! 423: + if (daemon->lease_change_command == NULL) return 0; /* ok */
! 424: +
! 425: + if (!lease) { /* if host has not been seen before lease is NULL */
! 426: + memset(&_lease, 0, sizeof(_lease));
! 427: + lease = &_lease;
! 428: + lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0);
! 429: + }
! 430: +
! 431: + uid = rand16();
! 432: + queue_script(ACTION_ACCESS, lease, NULL, now, uid);
! 433: +
! 434: + /* send all data to helper process */
! 435: + do
! 436: + {
! 437: + helper_write();
! 438: + } while (helper_buf_empty() == 0);
! 439: +
! 440: + /* wait for our event */
! 441: + ret = 0;
! 442: + do
! 443: + {
! 444: + ret = async_event( piperead, now, &ev, SCRIPT_TIMEOUT);
! 445: + }
! 446: + while(ev.priv != uid && ret >= 0);
! 447: +
! 448: + if (ret < 0 || ev.data != 0) /* timeout or error */
! 449: + {
! 450: + return -1;
! 451: + }
! 452: +
! 453: +#endif
! 454: + return 0; /* ok */
! 455: +}
! 456:
! 457: -size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
! 458: +size_t dhcp_reply(int piperead, struct dhcp_context *context, char *iface_name, int int_index,
! 459: size_t sz, time_t now, int unicast_dest, int *is_inform)
! 460: {
! 461: unsigned char *opt, *clid = NULL;
! 462: @@ -252,7 +293,7 @@
! 463: mac->netid.next = netid;
! 464: netid = &mac->netid;
! 465: }
! 466: -
! 467: +
! 468: /* Determine network for this packet. Our caller will have already linked all the
! 469: contexts which match the addresses of the receiving interface but if the
! 470: machine has an address already, or came via a relay, or we have a subnet selector,
! 471: @@ -329,7 +370,7 @@
! 472: my_syslog(LOG_INFO, _("Available DHCP range: %s -- %s"), daemon->namebuff, inet_ntoa(context_tmp->end));
! 473: }
! 474: }
! 475: -
! 476: +
! 477: mess->op = BOOTREPLY;
! 478:
! 479: config = find_config(daemon->dhcp_conf, context, clid, clid_len,
! 480: @@ -418,7 +459,7 @@
! 481: else
! 482: mess->yiaddr = lease->addr;
! 483: }
! 484: -
! 485: +
! 486: if (!message &&
! 487: !lease &&
! 488: (!(lease = lease_allocate(mess->yiaddr))))
! 489: @@ -641,7 +682,14 @@
! 490: memcpy(req_options, option_ptr(opt, 0), option_len(opt));
! 491: req_options[option_len(opt)] = OPTION_END;
! 492: }
! 493: -
! 494: +
! 495: + if (mess_type == DHCPREQUEST || mess_type == DHCPDISCOVER)
! 496: + if (check_access_script(piperead, lease, mess, now) < 0)
! 497: + {
! 498: + my_syslog(LOG_INFO, _("Ignoring client due to access script"));
! 499: + return 0;
! 500: + }
! 501: +
! 502: switch (mess_type)
! 503: {
! 504: case DHCPDECLINE:
! 505: Index: src/log.c
! 506: ===================================================================
! 507: --- src/log.c (revision 696)
! 508: +++ src/log.c (revision 821)
! 509: @@ -73,7 +73,7 @@
! 510:
! 511: if (!log_reopen(daemon->log_file))
! 512: {
! 513: - send_event(errfd, EVENT_LOG_ERR, errno);
! 514: + send_event(errfd, EVENT_LOG_ERR, errno, 0);
! 515: _exit(0);
! 516: }
! 517:
! 518: Index: src/lease.c
! 519: ===================================================================
! 520: --- src/lease.c (revision 696)
! 521: +++ src/lease.c (revision 821)
! 522: @@ -511,7 +511,7 @@
! 523: if (lease->old_hostname)
! 524: {
! 525: #ifndef NO_FORK
! 526: - queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
! 527: + queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now, 0);
! 528: #endif
! 529: free(lease->old_hostname);
! 530: lease->old_hostname = NULL;
! 531: @@ -520,7 +520,7 @@
! 532: else
! 533: {
! 534: #ifndef NO_FORK
! 535: - queue_script(ACTION_DEL, lease, lease->hostname, now);
! 536: + queue_script(ACTION_DEL, lease, lease->hostname, now, 0);
! 537: #endif
! 538: old_leases = lease->next;
! 539:
! 540: @@ -540,7 +540,7 @@
! 541: if (lease->old_hostname)
! 542: {
! 543: #ifndef NO_FORK
! 544: - queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now);
! 545: + queue_script(ACTION_OLD_HOSTNAME, lease, lease->old_hostname, now, 0);
! 546: #endif
! 547: free(lease->old_hostname);
! 548: lease->old_hostname = NULL;
! 549: @@ -552,7 +552,7 @@
! 550: (lease->aux_changed && (daemon->options & OPT_LEASE_RO)))
! 551: {
! 552: #ifndef NO_FORK
! 553: - queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now);
! 554: + queue_script(lease->new ? ACTION_ADD : ACTION_OLD, lease, lease->hostname, now, 0);
! 555: #endif
! 556: lease->new = lease->changed = lease->aux_changed = 0;
! 557:
! 558: Index: man/dnsmasq.8
! 559: ===================================================================
! 560: --- man/dnsmasq.8 (revision 696)
! 561: +++ man/dnsmasq.8 (revision 821)
! 562: @@ -724,12 +724,15 @@
! 563: .B \-6 --dhcp-script=<path>
! 564: Whenever a new DHCP lease is created, or an old one destroyed, the
! 565: binary specified by this option is run. The arguments to the process
! 566: -are "add", "old" or "del", the MAC
! 567: +are "add", "old", "access" or "del", the MAC
! 568: address of the host (or "<null>"), the IP address, and the hostname,
! 569: if known. "add" means a lease has been created, "del" means it has
! 570: been destroyed, "old" is a notification of an existing lease when
! 571: dnsmasq starts or a change to MAC address or hostname of an existing
! 572: lease (also, lease length or expiry and client-id, if leasefile-ro is set).
! 573: +The "access" keyword means that a request was just received and depending
! 574: +on the script exit status request for address will be granted, if exit status
! 575: +is zero or not if it is non-zero.
! 576: The process is run as root (assuming that dnsmasq was originally run as
! 577: root) even if dnsmasq is configured to change UID to an unprivileged user.
! 578: The environment is inherited from the invoker of dnsmasq, and if the
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>