start to track Daniel's version
[util-vserver.git] / src / naddress.c
diff --git a/src/naddress.c b/src/naddress.c
deleted file mode 100644 (file)
index a3a385f..0000000
+++ /dev/null
@@ -1,515 +0,0 @@
-// $Id: naddress.c 2584 2007-08-10 15:28:42Z dhozac $
-
-// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
-// Copyright (C) 2006 Daniel Hokka Zakrisson <daniel@hozac.com>
-// based on chbind.cc by Jacques Gelinas
-//  
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2, or (at your option)
-// any later version.
-//  
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//  
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include "vserver.h"
-#include "util.h"
-
-#include <lib/internal.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <unistd.h>
-#include <errno.h>
-#include <getopt.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#define ENSC_WRAPPERS_PREFIX   "naddress: "
-#define ENSC_WRAPPERS_IO       1
-#define ENSC_WRAPPERS_UNISTD   1
-#define ENSC_WRAPPERS_VSERVER  1
-#include "wrappers.h"
-
-#define CMD_HELP       0x1000
-#define CMD_VERSION    0x1001
-
-#define CMD_SILENT     0x2000
-#define CMD_NID                0x2001
-#define CMD_ADD                0x2002
-#define CMD_REMOVE     0x2003
-#define CMD_SET                0x2004
-#define CMD_IP         0x2010
-#define CMD_BCAST      0x2011
-#define CMD_MASK       0x2012
-#define CMD_RANGE      0x2013
-#define CMD_LBACK      0x2014
-
-int wrapper_exit_code = 255;
-
-
-static struct option const
-CMDLINE_OPTIONS[] = {
-  { "help",     no_argument,  0, CMD_HELP },
-  { "version",  no_argument,  0, CMD_VERSION },
-  { "silent",   no_argument,  0, CMD_SILENT },
-  { "add",      no_argument,  0, CMD_ADD },
-  { "remove",   no_argument,  0, CMD_REMOVE },
-  { "set",      no_argument,  0, CMD_SET },
-  { "nid",      required_argument, 0, CMD_NID },
-  { "ip",       required_argument, 0, CMD_IP },
-  { "mask",     required_argument, 0, CMD_MASK },
-  { "range",    required_argument, 0, CMD_RANGE },
-  { "bcast",    required_argument, 0, CMD_BCAST },
-  { "lback",    required_argument, 0, CMD_LBACK },
-  { 0,0,0,0 }
-};
-
-struct vc_ips {
-  struct vc_net_addr a;
-  struct vc_ips *next;
-};
-
-struct Arguments {
-  nid_t                nid;
-  struct vc_ips        head;
-  bool         is_silent;
-  bool         do_add;
-  bool         do_remove;
-  bool         do_set;
-};
-
-static void
-showHelp(int fd, char const *cmd, int res)
-{
-  WRITE_MSG(fd, "Usage:\n  ");
-  WRITE_STR(fd, cmd);
-  WRITE_MSG(fd,
-           " (--add|--remove|--set) [--silent] [--nid <nid>]\n"
-           "    [--ip <ip_num>[/<mask>]] [--bcast <broadcast>] [--] <commands> <args>*\n\n"
-           "Please report bugs to " PACKAGE_BUGREPORT "\n");
-
-  exit(res);
-}
-
-static void
-showVersion()
-{
-  WRITE_MSG(1,
-           "naddress " VERSION " -- bind to an ip and execute a program\n"
-           "This program is part of " PACKAGE_STRING "\n\n"
-           "Copyright (C) 2003,2004 Enrico Scholz\n"
-           "Copyright (C) 2006 Daniel Hokka Zakrisson\n"
-           VERSION_COPYRIGHT_DISCLAIMER);
-  exit(0);
-}
-
-/*
-       Check if a network device exist in /proc/net/dev.
-       This is used because ifconfig_ioctl triggers modprobe if requesting
-       information about non existant devices.
-
-       Return != 0 if the device exist.
-*/
-static bool
-existsDevice(char const *dev_raw)
-{
-  size_t       buf_size=8192;
-  char         dev[strlen(dev_raw)+2];
-
-  strcpy(dev, dev_raw);
-  strcat(dev, ":");
-  for (;;) {
-    char       buf[buf_size];
-    char *     pos;
-    bool       too_small;
-    int                fd=open("/proc/net/dev", O_RDONLY);
-    
-    if (fd==-1) return false;
-    too_small = EreadAll(fd, buf, buf_size);
-    close(fd);
-
-    if (too_small) {
-      buf_size *= 2;
-      continue;
-    }
-
-    pos = strstr(buf, dev);
-    return (pos && (pos==buf || pos[-1]==' ' || pos[-1]=='\n'));
-  }
-}
-
-static int ifconfig_ioctl(
-       int fd,
-       const char *ifname,
-       int cmd,
-       struct ifreq *ifr)
-{
-       strcpy(ifr->ifr_name, ifname);
-       return ioctl(fd, cmd, ifr);
-}
-
-/*
-       Fetch the IP number of an interface from the kernel.
-       Assume the device is already available in the kernel
-       Return -1 if any error.
-*/
-int ifconfig_getaddr (
-       const char *ifname,
-       uint32_t *addr,
-       uint32_t *mask,
-       uint32_t *bcast)
-{
-       int ret = -1;
-       if (existsDevice(ifname)){
-               int skfd = socket(AF_INET, SOCK_DGRAM, 0);
-               if (skfd != -1){
-                       struct ifreq ifr;
-                       if (addr != NULL && ifconfig_ioctl(skfd,ifname,SIOCGIFADDR, &ifr) >= 0){
-                               struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
-                               *addr = sin->sin_addr.s_addr;
-                               ret = 0;
-                       }
-                       if (mask != NULL && ifconfig_ioctl(skfd,ifname,SIOCGIFNETMASK, &ifr) >= 0){
-                               struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
-                               *mask = sin->sin_addr.s_addr;
-                               ret = 0;
-                       }
-                       if (bcast != NULL && ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){
-                               struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
-                               *bcast = sin->sin_addr.s_addr;
-                               ret = 0;
-                       }
-                       close (skfd);
-               }
-       }
-       return ret;
-}
-
-static int
-convertAddress(const char *str, uint16_t *type, void *dst)
-{
-  int  ret;
-  if (type) *type = VC_NXA_TYPE_IPV4;
-  ret = inet_pton(AF_INET, str, dst);
-  if (ret==0) {
-    if (type) *type = VC_NXA_TYPE_IPV6;
-    ret = inet_pton(AF_INET6, str, dst);
-  }
-  return ret > 0 ? 0 : -1;
-}
-
-static void
-ipv6PrefixToMask(struct in6_addr *mask, int prefix)
-{
-  int i;
-  mask->s6_addr32[0] = mask->s6_addr32[1] = mask->s6_addr32[2] = mask->s6_addr32[3] = 0;
-  for (i = 0; (i << 3) < prefix; i++) {
-    mask->s6_addr[i] = 0xff;
-  }
-  if ((i << 3) > prefix)
-    mask->s6_addr[i-1] = ~((1 << (prefix & 0x07)) - 1);
-}
-
-static int
-maskToPrefix(void *data, int limit)
-{
-  uint8_t *mask = data;
-  int prefix;
-  for (prefix = 0; prefix < limit && mask[prefix >> 3] & (1 << (prefix & 0x07)); prefix++)
-    ;
-  return prefix;
-}
-
-static void
-readIP(char const *str, struct vc_ips **ips, uint16_t type)
-{
-  if (ifconfig_getaddr(str, &(*ips)->a.vna_v4_ip.s_addr, &(*ips)->a.vna_v4_mask.s_addr, NULL)==-1) {
-    char               *pt;
-    char               tmpopt[strlen(str)+1];
-
-    strcpy(tmpopt,str);
-    pt = strchr(tmpopt,'/');
-    if (pt)
-      *pt++ = '\0';
-
-    if (convertAddress(tmpopt, &(*ips)->a.vna_type, &(*ips)->a.vna_v4_ip.s_addr) == -1) {
-      WRITE_MSG(2, "Invalid IP number '");
-      WRITE_STR(2, tmpopt);
-      WRITE_MSG(2, "'\n");
-      exit(wrapper_exit_code);
-    }
-
-    if (pt==0) {
-      switch ((*ips)->a.vna_type) {
-       case VC_NXA_TYPE_IPV4:
-         (*ips)->a.vna_v4_mask.s_addr = htonl(0xffffff00);
-         (*ips)->a.vna_prefix = 24;
-         break;
-       case VC_NXA_TYPE_IPV6:
-         (*ips)->a.vna_prefix = 64;
-         (*ips)->a.vna_v6_mask.s6_addr32[0] = (*ips)->a.vna_v6_mask.s6_addr32[1] = 0xffffffff;
-         (*ips)->a.vna_v6_mask.s6_addr32[2] = (*ips)->a.vna_v6_mask.s6_addr32[3] = 0x00000000;
-         break;
-       default: break;
-      }
-    }
-    else {
-      // Ok, we have a network size, not a netmask
-      if (strchr(pt,'.')==0 && strchr(pt,':')==0) {
-       unsigned long   sz, limit = 0;
-
-       switch ((*ips)->a.vna_type) {
-         case VC_NXA_TYPE_IPV4: limit =  32;   break;
-         case VC_NXA_TYPE_IPV6: limit = 128;   break;
-         default:                              break;
-       }
-
-       if (!isNumberUnsigned(pt, &sz, true) || sz > limit) {
-         WRITE_MSG(2, "Invalid prefix '");
-         WRITE_STR(2, pt);
-         WRITE_MSG(2, "'\n");
-         exit(wrapper_exit_code);
-       }
-
-       (*ips)->a.vna_prefix = sz;
-       switch ((*ips)->a.vna_type) {
-         case VC_NXA_TYPE_IPV4:
-           (*ips)->a.vna_v4_mask.s_addr = htonl(~((1 << (32 - sz)) - 1));
-           break;
-         case VC_NXA_TYPE_IPV6:
-           ipv6PrefixToMask(&(*ips)->a.vna_v6_mask, (*ips)->a.vna_prefix);
-           break;
-         default: break;
-       }
-      }
-      else {
-       int af, limit;
-       void *mask;
-       switch ((*ips)->a.vna_type) {
-         case VC_NXA_TYPE_IPV4:
-           af = AF_INET;
-           mask = &(*ips)->a.vna_v4_mask.s_addr;
-           limit = 32;
-           break;
-         case VC_NXA_TYPE_IPV6:
-           af = AF_INET6;
-           mask = (*ips)->a.vna_v6_mask.s6_addr32;
-           limit = 128;
-           break;
-         default:
-           return;
-       }
-       if (inet_pton(af, pt, mask) < 0) {
-         WRITE_MSG(2, "Invalid netmask '");
-         WRITE_STR(2, pt);
-         WRITE_MSG(2, "'\n");
-         exit(wrapper_exit_code);
-       }
-       (*ips)->a.vna_prefix = maskToPrefix(mask, limit);
-      }
-    }
-  }
-  else
-    (*ips)->a.vna_type = VC_NXA_TYPE_IPV4;
-  (*ips)->a.vna_type |= type;
-
-  (*ips)->next = calloc(1, sizeof(struct vc_ips));
-  *ips = (*ips)->next;
-}
-
-static void
-readBcast(char const *str, struct vc_ips **ips)
-{
-  uint32_t bcast;
-  if (ifconfig_getaddr(str, NULL, NULL, &bcast)==-1){
-    if (inet_pton(AF_INET, str, &bcast) < 0) {
-      WRITE_MSG(2, "Invalid broadcast number '");
-      WRITE_STR(2, optarg);
-      WRITE_MSG(2, "'\n");
-      exit(wrapper_exit_code);
-    }
-  }
-  (*ips)->a.vna_v4_ip.s_addr = bcast;
-  (*ips)->a.vna_type = VC_NXA_TYPE_IPV4 | VC_NXA_MOD_BCAST | VC_NXA_TYPE_ADDR;
-  (*ips)->next = calloc(1, sizeof(struct vc_ips));
-  *ips = (*ips)->next;
-}
-
-static void
-tellAddress(struct vc_net_addr *addr, bool silent)
-{
-  char buf[41];
-  int af;
-  void *address;
-  if (silent)
-    return;
-  switch (addr->vna_type & (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_IPV6)) {
-    case VC_NXA_TYPE_IPV4:
-      af = AF_INET;
-      address = &addr->vna_v4_ip.s_addr;
-      break;
-    case VC_NXA_TYPE_IPV6:
-      af = AF_INET6;
-      address = addr->vna_v6_ip.s6_addr32;
-      break;
-    default:
-      WRITE_MSG(1, " <unknown address type>");
-      return;
-  }
-  if (inet_ntop(af, address, buf, sizeof(buf)) == NULL) {
-    WRITE_MSG(1, " <conversion failed>");
-    return;
-  }
-  WRITE_MSG(1, " ");
-  WRITE_STR(1, buf);
-}
-
-static inline void
-doit(struct Arguments *args)
-{
-  struct vc_ips *ips;
-
-  if (args->do_set) {
-    struct vc_net_addr remove = { .vna_type = VC_NXA_TYPE_ANY };
-    if (vc_net_remove(args->nid, &remove) == -1) {
-      perror(ENSC_WRAPPERS_PREFIX "vc_net_remove()");
-      exit(wrapper_exit_code);
-    }
-  }
-
-  if (args->do_add || args->do_set) {
-    if (!args->is_silent)
-      WRITE_MSG(1, "Adding");
-    for (ips = &args->head; ips->next; ips = ips->next) {
-      tellAddress(&ips->a, args->is_silent);
-      if (vc_net_add(args->nid, &ips->a) == -1) {
-       if (!args->is_silent)
-         WRITE_MSG(1, "\n");
-       if (!args->is_silent)
-         WRITE_MSG(1, "\n");
-       perror(ENSC_WRAPPERS_PREFIX "vc_net_add()");
-       exit(wrapper_exit_code);
-      }
-    }
-    if (!args->is_silent)
-      WRITE_MSG(1, "\n");
-  }
-  else if (args->do_remove) {
-    if (!args->is_silent)
-      WRITE_MSG(1, "Removing");
-    for (ips = &args->head; ips->next; ips = ips->next) {
-      tellAddress(&ips->a, args->is_silent);
-      if (vc_net_remove(args->nid, &ips->a) == -1) {
-       if (!args->is_silent)
-         WRITE_MSG(1, "\n");
-       perror(ENSC_WRAPPERS_PREFIX "vc_net_remove()");
-       exit(wrapper_exit_code);
-      }
-    }
-    if (!args->is_silent)
-      WRITE_MSG(1, "\n");
-  }
-}
-
-int main (int argc, char *argv[])
-{
-  struct Arguments args = {
-    .nid       = VC_NOCTX,
-    .is_silent = false,
-    .do_add    = false,
-    .do_remove = false,
-    .do_set    = false,
-    .head      = { .next = NULL },
-  };
-  struct vc_ips *ips = &args.head;
-  
-  while (1) {
-    int                c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
-    if (c==-1) break;
-
-    switch (c) {
-      case CMD_HELP    :  showHelp(1, argv[0], 0);
-      case CMD_VERSION :  showVersion();
-      case CMD_SILENT  :  args.is_silent = true; break;
-      case CMD_NID     :  args.nid       = Evc_nidopt2nid(optarg,true); break;
-      case CMD_ADD     :  args.do_add    = true; break;
-      case CMD_REMOVE  :  args.do_remove = true; break;
-      case CMD_SET     :  args.do_set    = true; break;
-      case CMD_IP      :  readIP(optarg, &ips, VC_NXA_TYPE_ADDR);  break;
-      case CMD_MASK    :  readIP(optarg, &ips, VC_NXA_TYPE_MASK);  break;
-      case CMD_RANGE   :  readIP(optarg, &ips, VC_NXA_TYPE_RANGE); break;
-      case CMD_BCAST   :  readBcast(optarg, &ips); break;
-      case CMD_LBACK   :  readIP(optarg, &ips, VC_NXA_TYPE_ADDR | VC_NXA_MOD_LBACK); break;
-      default          :
-       WRITE_MSG(2, "Try '");
-       WRITE_STR(2, argv[0]);
-       WRITE_MSG(2, " --help' for more information.\n");
-       exit(wrapper_exit_code);
-       break;
-    }
-  }
-
-  if (args.nid == VC_NOCTX) args.nid = Evc_get_task_nid(0);
-
-  if (!args.do_add && !args.do_remove && !args.do_set) {
-    WRITE_MSG(2, "No operation specified; try '--help' for more information\n");
-    exit(wrapper_exit_code);
-  }
-  else if (((args.do_add ? 1 : 0) + (args.do_remove ? 1 : 0) + (args.do_set ? 1 : 0)) > 1) {
-    WRITE_MSG(2, "Multiple operations specified; try '--help' for more information\n");
-    exit(wrapper_exit_code);
-  }
-
-  doit(&args);
-
-  if (optind != argc)
-    Eexecvp (argv[optind],argv+optind);
-  return EXIT_SUCCESS;
-}
-
-#ifdef ENSC_TESTSUITE
-#include <assert.h>
-
-void test()
-{
-  struct vc_ip_mask_pair       ip;
-  uint32_t                     bcast;
-
-  bcast = 0;
-  readIP("1.2.3.4", &ip, &bcast);
-  assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xffffff00) && bcast==0);
-
-  readIP("1.2.3.4/8", &ip, &bcast);
-  assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xff000000) && bcast==0);
-
-  readIP("1.2.3.4/255.255.0.0", &ip, &bcast);
-  assert(ip.ip==ntohl(0x01020304) && ip.mask==ntohl(0xffff0000) && bcast==0);
-
-  readIP("localhost", &ip, &bcast);
-  assert(ip.ip==ntohl(0x7f000001) && ip.mask==ntohl(0xffffff00) && bcast==0);
-
-#if 0
-  if (ifconfig_getaddr("lo", &tmp, &tmp, &tmp)!=-1) {
-    readIP("lo", &ip, &bcast);
-    assert(ip.ip==ntohl(0x7f000001) && ip.mask==ntohl(0xff000000) && bcast==ntohl(0x7fffffff));
-  }
-#endif
-}
-#endif