kern_syscalls.c revision 83366
142433Sdfr/*-
242433Sdfr * Copyright (c) 1999 Assar Westerlund
342433Sdfr * All rights reserved.
442433Sdfr *
542433Sdfr * Redistribution and use in source and binary forms, with or without
642433Sdfr * modification, are permitted provided that the following conditions
742433Sdfr * are met:
842433Sdfr * 1. Redistributions of source code must retain the above copyright
942433Sdfr *    notice, this list of conditions and the following disclaimer.
1042433Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1142433Sdfr *    notice, this list of conditions and the following disclaimer in the
1242433Sdfr *    documentation and/or other materials provided with the distribution.
1342433Sdfr *
1442433Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1542433Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1642433Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1742433Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1842433Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1942433Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2042433Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2142433Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2242433Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2342433Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2442433Sdfr * SUCH DAMAGE.
2542433Sdfr *
2650477Speter * $FreeBSD: head/sys/kern/kern_syscalls.c 83366 2001-09-12 08:38:13Z julian $
2742433Sdfr */
2842433Sdfr
2942433Sdfr#include <sys/param.h>
3042433Sdfr#include <sys/sysproto.h>
3142433Sdfr#include <sys/sysent.h>
3242433Sdfr#include <sys/syscall.h>
3342433Sdfr#include <sys/module.h>
3442433Sdfr
3542756Speter/*
3642756Speter * Acts like "nosys" but can be identified in sysent for dynamic call
3742756Speter * number assignment for a limited number of calls.
3842756Speter *
3942756Speter * Place holder for system call slots reserved for loadable modules.
4042756Speter */
4142433Sdfrint
4283366Sjulianlkmnosys(struct thread *td, struct nosys_args *args)
4342756Speter{
4483366Sjulian	return(nosys(td, args));
4542756Speter}
4642756Speter
4742756Speterint
4883366Sjulianlkmressys(struct thread *td, struct nosys_args *args)
4969449Salfred{
5083366Sjulian	return(nosys(td, args));
5169449Salfred}
5269449Salfred
5369449Salfredint
5442433Sdfrsyscall_register(int *offset, struct sysent *new_sysent,
5542433Sdfr		 struct sysent *old_sysent)
5642433Sdfr{
5742433Sdfr       if (*offset == NO_SYSCALL) {
5842433Sdfr               int i;
5942433Sdfr
6042433Sdfr               for (i = 1; i < SYS_MAXSYSCALL; ++i)
6142433Sdfr                       if (sysent[i].sy_call == (sy_call_t *)lkmnosys)
6242433Sdfr                               break;
6342433Sdfr               if (i == SYS_MAXSYSCALL)
6442433Sdfr                       return ENFILE;
6542433Sdfr               *offset = i;
6642433Sdfr       } else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
6742433Sdfr               return EINVAL;
6869449Salfred       else if (sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
6969449Salfred				sysent[*offset].sy_call != (sy_call_t *)lkmressys)
7042433Sdfr               return EEXIST;
7142433Sdfr
7242433Sdfr       *old_sysent = sysent[*offset];
7342433Sdfr       sysent[*offset] = *new_sysent;
7442433Sdfr       return 0;
7542433Sdfr}
7642433Sdfr
7742433Sdfrint
7842433Sdfrsyscall_deregister(int *offset, struct sysent *old_sysent)
7942433Sdfr{
8042433Sdfr       if (*offset)
8142433Sdfr               sysent[*offset] = *old_sysent;
8242433Sdfr       return 0;
8342433Sdfr}
8442433Sdfr
8542433Sdfrint
8642433Sdfrsyscall_module_handler(struct module *mod, int what, void *arg)
8742433Sdfr{
8842433Sdfr       struct syscall_module_data *data = (struct syscall_module_data*)arg;
8942435Sdfr       modspecific_t ms;
9042433Sdfr       int error;
9142433Sdfr
9242433Sdfr       switch (what) {
9342433Sdfr       case MOD_LOAD :
9442433Sdfr               error = syscall_register(data->offset, data->new_sysent,
9542433Sdfr                                        &data->old_sysent);
9642433Sdfr               if (error)
9742433Sdfr                       return error;
9842435Sdfr	       ms.intval = *data->offset;
9942435Sdfr	       module_setspecific(mod, &ms);
10048269Sdfr               if (data->chainevh)
10148269Sdfr                       error = data->chainevh(mod, what, data->chainarg);
10248269Sdfr               return error;
10348269Sdfr
10442433Sdfr       case MOD_UNLOAD :
10548269Sdfr               if (data->chainevh) {
10648269Sdfr                       error = data->chainevh(mod, what, data->chainarg);
10748269Sdfr                       if (error)
10848269Sdfr                               return error;
10948269Sdfr               }
11042433Sdfr               error = syscall_deregister(data->offset, &data->old_sysent);
11148269Sdfr               return error;
11242433Sdfr       }
11348269Sdfr
11442433Sdfr       if (data->chainevh)
11542433Sdfr               return data->chainevh(mod, what, data->chainarg);
11642433Sdfr       else
11742433Sdfr               return 0;
11842433Sdfr}
119