/*
%%% copyright-cmetz
This software is Copyright 1996 by Craig Metz, All Rights Reserved.
The Inner Net License Version 2 applies to this software.
You should have received a copy of the license with this software. If
you didn't get a copy, you may request one from <license@inner.net>.

v0.02.
*/

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet6/in6.h>
#include <syslog.h>
#include <errno.h>
#include <getopt.h>

int debug = 0;

int main(int argc, char **argv)
{
  int af;
  union {
    struct sockaddr sa;
    struct sockaddr_in sin;
    struct sockaddr_in6 sin6;
  } peer;
  int peerlen;
  int i;

  if (argc < 3) {
    fprintf(stderr, "usage: addrform [-d] <family> <prog> [<arg>...]\n");
    exit(1);
  };

  while((i = getopt(argc, argv, "d")) != EOF) {
    switch(i) {
      case 'd':
        debug = 1;
        break;
    };
  };

  openlog("addrform", LOG_PID, LOG_DAEMON);

  if ((af = nrl_afnametonum(argv[optind])) < 0) {
    syslog(LOG_ERR, "don't know how to handle family %s", argv[optind]);
    exit(1);
  };

  peerlen = sizeof(peer);
  if (getpeername(0, (struct sockaddr *)&peer, &peerlen)) {
    syslog(LOG_ERR, "getpeername: %s(%d)", strerror(errno), errno);
    exit(1);
  };

  if (debug) {
    syslog(LOG_DEBUG, "old address:");
    dump_sockaddr((struct sockaddr *)&peer);
  };

  if (setsockopt(0, SOL_IPV6, IPV6_ADDRFORM, &af, sizeof(int))) {
    syslog(LOG_ERR, "setsockopt(0, SOL_IPV6, IPV6_ADDRFORM, ...) failed: %s(%d)", strerror(errno), errno);
    exit(1);
  };

  peerlen = sizeof(peer);
  if (getpeername(0, (struct sockaddr *)&peer, &peerlen)) {
    syslog(LOG_ERR, "getpeername: %s(%d)", strerror(errno), errno);
    exit(1);
  };

  if (debug) {
    syslog(LOG_DEBUG, "new address:");
    dump_sockaddr((struct sockaddr *)&peer);
  };

  execv(argv[optind + 1], &(argv[optind + 1]));
  syslog(LOG_ERR, "exec %s: %s(%d)", argv[optind + 1], strerror(errno), errno);
};
