Newer
Older
UbixOS / sys / kernel / kern_sysctl.c
@Charlie Root Charlie Root on 21 Jan 2018 9 KB Sync
/*-
 * Copyright (c) 2002-2018 The UbixOS Project.
 * All rights reserved.
 *
 * This was developed by Christopher W. Olsen for the UbixOS Project.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 * 1) Redistributions of source code must retain the above copyright notice, this list of
 *    conditions, the following disclaimer and the list of authors.
 * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
 *    conditions, the following disclaimer and the list of authors in the documentation and/or
 *    other materials provided with the distribution.
 * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/kern_sysctl.h>
#include <sys/sysproto_posix.h>
#include <sys/thread.h>
#include <ubixos/endtask.h>
#include <ubixos/kpanic.h>
#include <lib/kprintf.h>
#include <lib/kmalloc.h>
#include <assert.h>
#include <string.h>
#include <ubixos/errno.h>

static struct sysctl_entry *ctls = 0x0;

static struct sysctl_entry *sysctl_find(int *, int);
static struct sysctl_entry *sysctl_findMib(char *name, int namelen);

/* This is a cheat for now */
static void def_ctls() {
  int name[CTL_MAXNAME], name_len;
  uint32_t page_val = 0x1000;
  name[0] = 6;
  name[1] = 7;
  name_len = 2;
  sysctl_add(name, name_len, "pagesizes", &page_val, sizeof(uint32_t));

  /* Clock Rate */
  name[0] = 1;
  name[1] = 12;
  page_val = 0x3E8;
  sysctl_add(name, name_len, "page_size", &page_val, sizeof(uInt32));

  /* KERN: OS Release */
  name[0] = 1;
  name[1] = 24;
  page_val = 101000;
  sysctl_add(name, name_len, "kern.osreldate", &page_val, sizeof(uInt32));

  /* KERN: User Stack */
  name[0] = 1;
  name[1] = 33;
  page_val = 0xCBE8000;
  sysctl_add(name, name_len, "page_size", &page_val, sizeof(uInt32));

  /* KERN: ARND */
  name[0] = 1;
  name[1] = 37;
  page_val = 0x1;
  sysctl_add(name, name_len, "kern_arnd", &page_val, sizeof(uint32_t));

  /* HW: NCPU */
  name[0] = 6;
  name[1] = 3;
  page_val = 0x1;
  sysctl_add(name, name_len, "hw.ncpu", &page_val, sizeof(uint32_t));

  name[0] = 9;
  name[1] = 20;
  page_val = 0x4000;
  sysctl_add(name, name_len, "p1003_1b.pagesize", &page_val, sizeof(uint32_t));
}

int sysctl_init() {
  struct sysctl_entry *tmpCtl = 0x0;
  if (ctls != 0x0) {
    kprintf("sysctl already Initialized\n");
    while (1)
      ;
  }

  ctls = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  ctls->prev = 0x0;
  ctls->id = CTL_UNSPEC;
  ctls->children = 0x0;
  sprintf(ctls->name, "unspec");

  tmpCtl = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->prev = ctls;
  tmpCtl->id = CTL_KERN;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "kern");
  ctls->next = tmpCtl;

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_VM;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "vm");

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_VFS;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "vfs");

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_NET;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "net");

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_DEBUG;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "debug");

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_HW;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "hw");

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_MACHDEP;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "machdep");

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_USER;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "user");

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_P1003_1B;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "p1003_1b");

  tmpCtl->next = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
  tmpCtl->next->prev = tmpCtl;
  tmpCtl = tmpCtl->next;
  tmpCtl->id = CTL_UBIX;
  tmpCtl->children = 0x0;
  sprintf(tmpCtl->name, "ubix");

  def_ctls();

  return (0x0);
}

int __sysctl(struct thread *td, struct sysctl_args *uap) {
  struct sysctl_entry *tmpCtl = 0x0;
  int i = 0;

  if (ctls == 0x0)
    K_PANIC("sysctl not initialized");

  if (uap->newlen < 0) {
    kprintf("Changing Not supported yet.\n");
    endTask(_current->id);
  }

  tmpCtl = sysctl_find(uap->name, uap->namelen);
  if (tmpCtl == 0x0) {
    kprintf("Invalid CTL\n");
    for (i = 0x0; i < uap->namelen; i++)
      kprintf("(%i)", uap->name[i]);
    kprintf("\n");
    endTask(_current->id);
  }

  if ((uint32_t) uap->oldlenp < tmpCtl->val_len)
    memcpy(uap->oldp, tmpCtl->value, (uInt32) uap->oldlenp);
  else
    memcpy(uap->oldp, tmpCtl->value, tmpCtl->val_len);

  td->td_retval[0] = 0x0;

  return (0x0);
}

int sys_sysctl(struct thread *td, struct sys_sysctl_args *args) {
  struct sysctl_entry *tmpCtl = 0x0;
  int i = 0;

  if (ctls == 0x0)
    K_PANIC("sysctl not initialized");

  if (args->newlenp < 0) {
    kprintf("Changing Not supported yet.\n");
    endTask(_current->id);
  }

  if (args->namelen == 2 && args->name[0] == 0 && args->name[1] == 3) {
    kprintf("name_to_mib: %s", args->newp);
   // tmpCtl = sysctl_findMib(args->newp, args->namelen);
td->td_retval[0] = ENOENT;
return(-1);
  }
  else {
  tmpCtl = sysctl_find(args->name, args->namelen);
  }

  if (tmpCtl == 0x0) {
    kprintf("Invalid CTL: ");
    for (i = 0x0; i < args->namelen; i++)
      kprintf("(%i)", (int) args->name[i]);
    kprintf("\n");
    td->td_retval[0] = -1;
    return (-1);
  }

  if ((uint32_t) args->oldlenp < tmpCtl->val_len)
    memcpy(args->oldp, tmpCtl->value, (uInt32) args->oldlenp);
  else
    memcpy(args->oldp, tmpCtl->value, tmpCtl->val_len);

  td->td_retval[0] = 0x0;

  return (0x0);
}

static struct sysctl_entry *sysctl_find(int *name, int namelen) {
  int i = 0x0;
  struct sysctl_entry *tmpCtl = 0x0;
  struct sysctl_entry *lCtl = ctls;

  /* Loop Name Len */
  for (i = 0x0; i < namelen; i++) {
    for (tmpCtl = lCtl; tmpCtl != 0x0; tmpCtl = tmpCtl->next) {
      //kprintf("ctlName: [%s], ctlId; [%i]\n",tmpCtl->name,tmpCtl->id);
      if (tmpCtl->id == name[i]) {
        if ((i + 1) == namelen) {
          return (tmpCtl);
        }
        lCtl = tmpCtl->children;
        break;
      }
    }
  }
  return (0x0);
}


static struct sysctl_entry *sysctl_findMib(char *name, int namelen) {
  int i = 0x0;
  struct sysctl_entry *tmpCtl = 0x0;
  struct sysctl_entry *lCtl = ctls;

  char *mib = (char *) strtok( (char *) name, "." );


  kprintf("FMIB: %s", mib);
  /* Loop Name Len */
  for (i = 0x0; i < namelen; i++) {
  for (tmpCtl = lCtl; tmpCtl != 0x0; tmpCtl = tmpCtl->next) {
    if (strcmp(mib, tmpCtl->name) == 0x0) {
       kprintf("ctlName: [%s], ctlId: [%i]",tmpCtl->name,tmpCtl->id);
        if ((i + 1) == namelen) {
          return (tmpCtl);
        }
        mib = strtok( NULL, "\n" );
        kprintf("SMIB: %s", mib);
        lCtl = tmpCtl->children;
        break;
    }
  }
  }
  return (0x0);
}


int sysctl_add(int *name, int namelen, char *str_name, void *buf, int buf_size) {
  struct sysctl_entry *tmpCtl = 0x0;
  struct sysctl_entry *newCtl = 0x0;

  /* Check if it exists */
  tmpCtl = sysctl_find(name, namelen);
  if (tmpCtl != 0x0) {
    kprintf("Node Exists!\n");
    while (1)
      ;
  }

  /* Get Parent Node */
  tmpCtl = sysctl_find(name, namelen - 1);
  if (tmpCtl == 0x0) {
    kprintf("Parent Node Non Existant\n");
    return (-1);
  }
  if (tmpCtl->children == 0x0) {
    tmpCtl->children = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
    tmpCtl->children->children = 0x0;
    tmpCtl->children->prev = 0x0;
    tmpCtl->children->next = 0x0;
    tmpCtl->children->id = name[namelen - 1];
    sprintf(tmpCtl->children->name, str_name);
    tmpCtl->children->value = (void *) kmalloc(buf_size);
    memcpy(tmpCtl->children->value, buf, buf_size);
    tmpCtl->children->val_len = buf_size;
  }
  else {
    newCtl = (struct sysctl_entry *) kmalloc(sizeof(struct sysctl_entry));
    newCtl->prev = 0x0;
    newCtl->next = tmpCtl->children;
    newCtl->children = 0x0;
    newCtl->id = name[namelen - 1];
    sprintf(newCtl->name, str_name);
    newCtl->value = (void *) kmalloc(buf_size);
    memcpy(newCtl->value, buf, buf_size);
    newCtl->val_len = buf_size;
    tmpCtl->children->prev = newCtl;
    tmpCtl->children = newCtl;
  }

  return (0x0);
}

/***
 END
 ***/