Конфигурируем DHCP-серверы и настраиваем динамические обновления DNS
Сергей Супрунов
# cd /usr/ports/net/isc-dhcp30-server/
# make install
# fetch http://ftp.isc.org/isc/dhcp/dhcp-4.1.0.tar.gz
# tar xzvf dhcp-4.1.0.tar.gz
# cd dhcp-4.1.0
# ./configure
# make
# make install
# cd /usr/ports/net/isc-dhcp30-server
# mkdir work
# make apply-slist
# cp work/isc-dhcpd /usr/local/etc/rc.d/
$ grep bpf /usr/src/sys/`uname -p`/conf/`uname -i`
dhcpd_enable="YES"
dhcpd_ifaces="nfe0"
# Доменное имя. Имена хостов клиентов будут дополняться до FQHN
option domain-name "example.org";
# DNS-серверы, которые будут предлагаться клиентам.
# Можно использовать и IP-адреса оных
option domain-name-servers ns1.example.org, ns2.example.org;
# «Умолчальное» и максимальное времена аренды адреса в секундах
default-lease-time 3600;
max-lease-time 86400;
# Является ли сервер авторитативным
authoritative;
# Способ динамического обновления DNS.
# Подробнее поговорим позже, сейчас отключим
ddns-update-style none;
# Источник сообщений для записи логов через syslogd
log-facility local7;
# Объявление подсети
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.200 192.168.1.249;
option routers 192.168.1.1;
}
local7.* /var/log/dhcpd.log
/etc/rc.d/syslogd restart
shared-network rl0-net {
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.199;
option routers 192.168.1.1;
}
subnet 192.168.2.0 netmask 255.255.255.0 {
range 192.168.2.100 192.168.2.199;
option routers 192.168.2.1;
}
}
class "a-clients" {
match if substring (option host-name, 0, 1) = "a";
}
subnet 10.0.0.0 netmask 255.255.255.0 {
pool {
allow members of "a-clients";
range 10.0.0.10 10.0.0.19;
}
pool {
deny members of "a-clients";
range 10.0.0.20 10.0.0.99;
}
}
host acer {
hardware ethernet 00:1b:38:22:8c:17;
fixed-address 10.161.193.177;
}
group {
...общие опции...
host acer { ...специфичные для хоста опции ...}
host fuji { ...специфичные для хоста опции ...}
}
# Объявляем ключ доступа (можно задавать и в каждой зоне, но так удобнее)
key DHCP_KEY {
algorithm hmac-md5;
secret "c20f9433f5f5ecf1f245a6112d7dd651";
};
# «Прямая» зона
zone "test.inr" {
type master;
allow-update { key DHCP_KEY; };
file "master/test.inr";
};
# «Обратная» зона
zone "0.0.10.in-addr.arpa" {
type master;
allow-update { key DHCP_KEY; };
file "master/0.0.10.in-addr.arpa";
};
$ echo 'Super secret key' | mmencode
$ echo 'Super secret key' | md5
$ dnssec-keygen -a HMAC-MD5 -b 128 -n HOST test.inr
$ ls -l Ktest.inr.+157+41531.*
include "key.conf";
zone "test.inr" {
type master;
update-policy {
grant DHCP_KEY subdomain test.inr A TXT;
};
file "master/test.inr";
};
# Указываем метод обновления (существует ещё ad-hoc, но он не рекомендуется)
ddns-update-style interim;
# Описываем тот же ключ (можно просто скопировать из named.conf – синтаксис тот же)
# Если оператор key вынесен в отдельный файл, можно, как и в named.conf, использовать оператор include:
### include "key.conf";
key DHCP_KEY {
algorithm hmac-md5;
secret "c20f9433f5f5ecf1f245a6112d7dd651";
}
# «Прямая» зона, которую нужно обновлять
zone test.inr {
primary 10.0.0.220;
key DHCP_KEY;
}
# «Обратная» зона, которую нужно обновлять
zone 0.0.10.in-addr.arpa {
primary 10.0.0.220;
key DHCP_KEY;
}
# cd /usr/ports/net-mgmt/wide-dhcp
# make install
# Создаём подсеть (сюда выносим общие параметры:
# маску, шлюз и широковещательный адрес)
subnet:snmk=255.255.255.0:rout=10.0.0.1:brda=10.0.0.255:
# Далее идут описания каждого адреса пула
# (первое поле – просто идентификатор записи,
# далее задаются IP-адрес, время аренды (по умолч. и макс.),
# а также подключается определённая выше конфигурация subnet)
ip198: :ipad=10.0.0.198:dfll=3600:maxl=7200:tblc=subnet:
ip199: :ipad=10.0.0.199:dfll=3600:maxl=7200:tblc=subnet:
dhcprelay_enable='YES'
dhcprelay_server='10.0.0.220'
dhcprelay_ifaces='ed0
$ nsupdate -v
> server 10.0.0.220
> key DHCP_KEY c20f9433f5f5ecf1f245a6112d7dd651
> update add new.test.inr 300 A 10.1.1.15
> show
> send
> quit
-----------------------------------------------------------------------------------------------------------------
Заменяем сервер MS Exchange. Установка Horde Groupware
Рашид Ачилов
# cd /usr/ports/www/horde-meta
# make
Listen 18511
ServerName horde.shelton.net
ServerAdmin webmaster@shelton.net
DocumentRoot "/usr/local/www/vhosts/horde/"
ErrorLog "/usr/local/www/log/horde/httpd"
CustomLog "/usr/local/www/log/horde/access" common
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
Include etc/apache22/extra/httpd-languages.conf
AddType application/x-tar .tgz
AddEncoding x-compress .Z
AddEncoding x-gzip .gz .tgz
AddHandler cgi-script .cgi
AllowOverride None
Order allow,deny
Allow from all
cd ../scripts/sql
mysql -u root -p < create.mysql.sql
mysql> show create database 'horde';
$conf['auth']['admins'] = array('Administrator');
$conf['auth']['driver'] = 'auto';
$conf['auth']['params'] = array('username' => 'Administrator');
-----------------------------------------------------------------------------------------------------------------
Sun Secure Global Desktop. Все ваши приложения в окне браузера
Антон Борисов
# rpm -ih tta-4.50-907.i386.rpm
# /tmp/SGDCreateUsers.sh
# rpm -ih tta-4.50-907.i386.rpm
# /opt/tarantella/bin/tarantella start
$ ~/bin/ttatcc
#!/bin/sh
rdesktop-vrdp win2003server.intra.net -u RemoteAccessUser -g 1024x768
# /opt/tarantella/bin/tarantella object new_person
# /opt/tarantella/bin/tarantella license info
-----------------------------------------------------------------------------------------------------------------
Управляем доступом к ресурсам домена на основе Windows Server
Вадим Андросов
Set objSWbemServices = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\CIMv2")
select * from __instanceCreationevent where targetinstance isa 'Win32_NTLogEvent' and targetinstance.EventIdentifier = 672
Листинг 1. Создание фильтра событий
Set eventFilterClass = objSWbemServices.Get("__EventFilter")
set userFilter = eventFilterClass.SpawnInstance_()
userFilter.Name = "SecureCompFilter"
userFilter.QueryLanguage = "WQL"
userFilter.Query = "select * from __instancecreationevent " & "where targetinstance isa 'Win32_NTLogEvent' " & "and targetinstance.EventIdentifier = 672"
userFilter.EventNamespace = "root\CIMv2"
userFilter.Put_()
mofcomp %SYSTEMROOT%\system32\wbem\scrcons.mof
Листинг 2. Создание объекта реакции на событие
Set consumerClass = objSWbemServices.Get("ActiveScriptEventConsumer")
set userConsumer = consumerClass.SpawnInstance_()
userConsumer.Name = "RunSecureCompScript"
userConsumer.ScriptText = "createObject("& chr(34) & "SecureComputer.EventHandler" & chr(34) & ").handle(targetEvent.targetInstance)"
userConsumer.ScriptingEngine = "VBScript"
userConsumer.Put_()
createObject(SecureComputer.EventHandler).handle(targetEvent.targetInstance)
Листинг 3. Объект для связи фильтра события с его обработчиком
Set bindingClass = objSWbemServices.Get("__FilterToConsumerBinding")
set userBinder = bindingClass.SpawnInstance_()
userBinder.Filter = "__EventFilter.Name=" & chr(34) & "SecureCompFilter" & chr(34)
userBinder.Consumer = "ActiveScriptEventConsumer.Name=" & chr(34) & "RunSecureCompScript" & chr(34)
userBinder.Put_()
Листинг 4. Отключение прослушивания событий
Set objWIMService = GetObject("winmgmts:\\.\root\CIMv2")
Set objList = objWIMService.ExecQuery("references of {__EventFilter.Name='SecureCompFilter'}")
For each objInst in objList
objInst.Delete_
Next
Set obj = GetObject("winmgmts:\\.\root\CIMv2:" & "ActiveScriptEventConsumer='RunSecureCompScript'")
obj.Delete_
Set obj = GetObject("winmgmts:\\.\root\CIMv2:" & "__EventFilter='SecureCompFilter'")
obj.Delete_
Листинг 5. Заготовка класса SecureComputer.EventHandler
Function bindUserComp(ip, userName)
if ip = "127.0.0.1" then exit function
set info = createObject("ADSystemInfo")
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCOmmand.ActiveConnection = objConnection
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
Set rootDSE = GetObject("LDAP://RootDSE")
objCommand.CommandText = "Select ADsPath from 'LDAP://" & rootDSE.Get("defaultNamingContext") & "' " & "Where objectClass='user' and " & "samAccountName ='" & userName & "'"
Set objRecordSet = objCommand.Execute
if objRecordSet.EOF then exit function
objRecordSet.MoveFirst
Set user = getObject(objRecordSet.Fields(0).value)
Set objWMIService = GetObject("winmgmts:\\.\root\MicrosoftDNS")
Set colItems = objWMIService.ExecQuery("SELECT * FROM MicrosoftDNS_AType " & "WHERE IPAddress = '" & ip & "' and domainName = '" & info.domainDNSName & "'")
For Each objItem in colItems
if objItem.OwnerName <> info.domainDNSName then DNSHostName = objItem.OwnerName
next
objCommand.CommandText = "Select ADsPath from 'LDAP://" & rootDSE.Get("defaultNamingContext") & "' " & "Where objectClass='computer' and " & "DNSHostName ='" & DNSHostName & "'"
Set objRecordSet = objCommand.Execute
objRecordSet.MoveFirst
Set computer = getObject(objRecordSet.Fields(0).value)
group = null
objCommand.CommandText = "select ADSPath from '" & computer.parent & "' where objectClass = 'group' and cn = '" & computer.cn & "_cg'"
Set objRecordSet = objCommand.Execute
if not objRecordSet.EOF then
objRecordSet.MoveFirst
set group = getObject(objRecordSet.Fields(0).value)
end if
if not isNull(group) then
if group.isMember(user.ADSPath) then exit function
end if
for each ug in user.groups
if len(ug.cn)>3 then
if right(ug.cn,3) = "_cg" then
ug.remove user.ADSPath
end if
end if
next
if not isNull(group) then group.add(user.ADSPath)
End Function
-----------------------------------------------------------------------------------------------------------------
Новые возможности Nmap 5.00 – программы для исследования безопасности сетей
Игорь Штомпель
./configure && make
sudo make install
ncat -l --proxy-type http localhost 8080
ndiff [options] {a.xml} {b.xml}
man ndiff
www.yandex.ru www.google.com www.mail.ru
nmap -sP -PE -PS22,25,80 -PA21,23,80,3389 -PU -PO --traceroute www.yandex.ru www.google.com www.mail.ru
-----------------------------------------------------------------------------------------------------------------
Электронная проходная своими руками
Андрей Луконькин
Процедура ШтрихкодПриИзменении(Элемент)
ЭлементыФормы.НадписьОшибкаСотрудника.Заголовок = "";
ЭлементыФормы.НадписьНайденныйСотрудник.Заголовок = "";
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ФизическиеЛица.Штрихкод,
| ФизическиеЛица.Ссылка
|ИЗ
| Справочник.ФизическиеЛица КАК ФизическиеЛица
|ГДЕ
| ФизическиеЛица.Штрихкод = &Штрихкод";
Запрос.УстановитьПараметр("Штрихкод", Штрихкод);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
НайденныйСотрудник = Выборка.Ссылка;
ЭлементыФормы.НадписьНайденныйСотрудник.Заголовок = НайденныйСотрудник.Наименование;
Штрихкод="";
ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.Штрихкод;
Иначе
ЭлементыФормы.НадписьОшибкаСотрудника.Заголовок = "Не найден сотрудник с таким штрихкодом! Обратитесь к администратору.";
Штрихкод="";
ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.Штрихкод;
возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПриходУходСотрудниковСрезПоследних.ФизЛицо,
| ПриходУходСотрудниковСрезПоследних.Вход,
| ПриходУходСотрудниковСрезПоследних.Выход,
| ПриходУходСотрудниковСрезПоследних.Период
|ИЗ
| РегистрСведений.ПриходУходСотрудников.СрезПоследних(&ТекДата, ФизЛицо.Ссылка = &Найденный) КАК ПриходУходСотрудниковСрезПоследних";
Запрос.УстановитьПараметр("ТекДата", ТекущаяДата());
Запрос.УстановитьПараметр("Найденный", НайденныйСотрудник.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
//Проверим, последний раз входил или выходил
Если Выборка.Вход Тогда
//Значит выходим
НовСтрока = СписокПрошедших.Добавить();
НовСтрока.Сотрудник = НайденныйСотрудник;
НовСтрока.Выход = ТекущаяДата();
НовЗапись = РегистрыСведений.ПриходУходСотрудников.СоздатьМенеджерЗаписи();
НовЗапись.ФизЛицо = НайденныйСотрудник;
НовЗапись.Выход = Истина;
НовЗапись.Период = ТекущаяДата();
НовЗапись.Записать();
ЭлементыФормы.СписокПрошедших.ТекущаяСтрока = НовСтрока;
Иначе
//Входим
НовСтрока = СписокПрошедших.Добавить();
НовСтрока.Сотрудник = НайденныйСотрудник;
НовСтрока.Вход = ТекущаяДата();
НовЗапись = РегистрыСведений.ПриходУходСотрудников.СоздатьМенеджерЗаписи();
НовЗапись.ФизЛицо = НайденныйСотрудник;
НовЗапись.Вход = Истина;
НовЗапись.Период = ТекущаяДата();
НовЗапись.Записать();
ЭлементыФормы.СписокПрошедших.ТекущаяСтрока = НовСтрока;
Конецесли;
Иначе
//Не нашли, значит вход
НовСтрока = СписокПрошедших.Добавить();
НовСтрока.Сотрудник = НайденныйСотрудник;
НовСтрока.Вход = ТекущаяДата();
НовЗапись = РегистрыСведений.ПриходУходСотрудников.СоздатьМенеджерЗаписи();
НовЗапись.ФизЛицо = НайденныйСотрудник;
НовЗапись.Вход = Истина;
НовЗапись.Период = ТекущаяДата();
НовЗапись.Записать();
ЭлементыФормы.СписокПрошедших.ТекущаяСтрока = НовСтрока;
Конецесли;
КонецПроцедуры
Процедура ПриОткрытии()
СписокПрошедших.Колонки.Добавить("Сотрудник");
СписокПрошедших.Колонки.Добавить("Вход");
СписокПрошедших.Колонки.Добавить("Выход");
ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.Штрихкод;
КонецПроцедуры
Процедура КнопкаВыполнитьНажатие(Кнопка)
Если (НЕ ЗначениеЗаполнено(НачПериода))
ИЛИ (НЕ ЗначениеЗаполнено(КонПериода)) Тогда
Предупреждение("Выберите период!");
Возврат;
КонецЕсли;
//Создание объекта MS Excel
Excel = Новый COMОбъект("Excel.Application");
//Создаём новую книгу в Excel
Excel.WorkBooks.Add();
//Выводим текст заголовка документа
Excel.WorkBooks(1).WorkSheets("Лист1").cells(1,1).value = "Таб. №";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(1,2).value = "Сотрудник";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(1,3).value = "Дата";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(1,4).value = "Время";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(1,5).value = "Подразделение";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(1,6).value = "Событие";
//Заполняем со 2-й строки
Счетчик = 2;
//Выберем записи о входах-выходах за период
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПриходУходСотрудников.Период,
| ПриходУходСотрудников.ФизЛицо,
| ПриходУходСотрудников.Вход,
| ПриходУходСотрудников.Выход
|ИЗ
| РегистрСведений.ПриходУходСотрудников КАК ПриходУходСотрудников
|ГДЕ
| ПриходУходСотрудников.Период МЕЖДУ &НачПериода И &КонПериода";
Запрос.УстановитьПараметр("НачПериода", НачалоДня(НачПериода));
Запрос.УстановитьПараметр("КонПериода", КонецДня(КонПериода));
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,1).NumberFormat = "@";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,1).value = Строка(Выборка.ФизЛицо.ТабНомер);
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,2).NumberFormat = "@";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,2).value = Строка(Выборка.ФизЛицо);
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,3).NumberFormat = "@";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,3).value = Строка(Формат(Выборка.Период,"ДЛФ=D"));
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,4).NumberFormat = "@";
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,4).value = Строка(Формат(Выборка.Период,"ДЛФ=T"));
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,6).NumberFormat = "@";
Если Выборка.Вход Тогда
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,6).value = "Вход";
ИначеЕсли Выборка.Выход Тогда
Excel.WorkBooks(1).WorkSheets("Лист1").cells(Счетчик,6).value = "Выход";
КонецЕсли;
Счетчик = Счетчик + 1;
КонецЦикла;
//Записываем файл Excel
Попытка
Excel.ActiveWorkBook.SaveAs(СокрЛП(Путь)+ИмяФайла);
Исключение
Сообщить("Неудачная попытка сохранения файла");
КонецПопытки;
//Закрываем книгу Excel
Excel.ActiveWorkBook.Close();
КонецПроцедуры
Процедура ВыбПериодНажатие(Элемент)
НастройкаПериода = Новый НастройкаПериода;
НастройкаПериода.УстановитьПериод(НачПериода,?(КонПериода='0001-01-01', КонПериода, КонецДня(КонПериода)));
НастройкаПериода.РедактироватьКакИнтервал = Истина;
НастройкаПериода.РедактироватьКакПериод = Истина;
НастройкаПериода.ВариантНастройки = ВариантНастройкиПериода.Период;
Если НастройкаПериода.Редактировать() Тогда
НачПериода = НастройкаПериода.ПолучитьДатуНачала();
КонПериода = НастройкаПериода.ПолучитьДатуОкончания();
КонецЕсли;
ИмяФайла = Строка(Формат(НачПериода,"ДЛФ=D"))+".xls";
КонецПроцедуры
Процедура НачПериодаПриИзменении(Элемент)
ИмяФайла = Строка(Формат(НачПериода,"ДЛФ=D"))+".xls";
КонецПроцедуры
-----------------------------------------------------------------------------------------------------------------
Основы Spring
Андрей Уваров
package com.andrewdashin.examples.spring.beans;
public interface HelloBean {
public void helloWorld();
}
package com.andrewdashin.examples.spring.beans;
public class HelloBeanImpl implements HelloBean {
String hello;
public void helloWorld() {
System.out.println(hello);
}
public void setHello(String hello) {
this.hello = hello;
}
}
Hello World!
package com.andrewdashin.examples.spring;
import com.andrewdashin.examples.spring.beans.*;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("resources/beans.xml");
HelloBean bean = (HelloBean) context.getBean("helloBean");
bean.helloWorld();
}
}
Manifest-Version: 1.0
Created-By: 1.5.0_13 (Apple Inc.)
Main-Class: com.andrewdashin.examples.spring.Main
Class-Path: lib/spring.jar lib/commons-logging-1.1.jar
javac -cp lib/spring.jar -d ./src/com/andrewdashin/examples/spring/Main.java src/com/andrewdashin/examples/spring/beans/HelloBean.java src/com/andrewdashin/examples/spring/beans/HelloBeanImpl.java
jar cvfm main.jar MANIFEST.MF com/andrewdashin/examples/spring/Main.class com/andrewdashin/examples/spring/beans/HelloBean.class com/andrewdashin/examples/spring/beans/HelloBeanImpl.class resources/context.xml
new ClassPathXmlApplicationContext("resources/context.xml")
-----------------------------------------------------------------------------------------------------------------
Пишем первые модули на Erlang
Дмитрий Васильев
-module(geometry).
-export([area/1]).
% Функция для вычисления площади
area({square, Side}) ->
Side * Side;
area({rectangle, Width, Height}) ->
Width * Height;
area({circle, Radius}) ->
3.1415926 * Radius * Radius.
1> c(geometry).
2> geometry:area({circle, 20}).
3> geometry:area({square, 20}).
4> geometry:area({rectangle, 10, 20}).
5> geometry:area({triangle, 10, 20, 30}).
-module(persons).
-export([person_list/1]).
person_list(Persons) ->
person_list(Persons, 0).
person_list([{person, FirstName, LastName} | Persons], N) ->
io:format("~s ~s~n", [FirstName, LastName]),
person_list(Persons, N + 1);
person_list([], N) ->
io:format("Total: ~p~n", [N]).
1> c(persons).
2> persons:person_list([]).
3> persons:person_list([{person, "Joe", "Armstrong"}]).
4> persons:person_list([{person, "Joe", "Armstrong"},
4> {person, "Mike", "Williams"},
4> {person, "Robert", "Virding"}]).
max(X, Y) when X > Y ->
X;
max(_X, Y) ->
Y.
case is_boolean(Variable) of
true ->
1;
false ->
0
end
if
X > Y ->
true;
true ->
false
end
-module(times).
-export([times/1]).
times(N) ->
fun
(X) when is_number(X) ->
X * N;
(_) ->
erlang:error(number_expected)
end.
1> c(times).
2> N2 = times:times(2).
3> N2(4).
4> N10 = times:times(10).
5> N10(4).
6> Double = times:times(2).
7> lists:map(Double, [1, 2, 3, 4]).
1> catch 2 + 2.
2> catch 2 + a.
3> catch exit("Exit").
4> catch throw("Throw").
5> catch erlang:error("Error").
try 2 + a of
Value ->
ok
catch
error:_ ->
error
end.
-----------------------------------------------------------------------------------------------------------------