4697-1 (Реализация сети в операционной системе Linux), страница 3
Описание файла
Документ из архива "Реализация сети в операционной системе Linux", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "курсовые/домашние работы", в предмете "информатика, программирование" в общих файлах.
Онлайн просмотр документа "4697-1"
Текст 3 страницы из документа "4697-1"
*
* Portions (C) Copyright 1993, 1994 by Bjorn Ekwall
* The Author may be reached as bj0rn@blox.se
/*
* Если у нас хороший пакет то забираем его из адаптера
*/
static void
de600_rx_intr(struct net_device *dev)
{
struct sk_buff *skb;
unsigned long flags;
int i;
int read_from;
int size;
register unsigned char *buffer;
save_flags(flags);
cli();
/* Определяем размер пакета */
size = de600_read_byte(RX_LEN, dev); /* нижния байт */
size += (de600_read_byte(RX_LEN, dev) << 8); /* верхний байт */
size -= 4; /* Ignore trailing 4 CRC-bytes */
/* Сообщаем адаптеру куда ложить следующий пакет и получаем */
read_from = rx_page_adr();
next_rx_page();
de600_put_command(RX_ENABLE);
restore_flags(flags);
if ((size 1535)) {
printk("%s: Bogus packet size %d.\n", dev->name, size);
if (size > 10000)
adapter_init(dev);
return;
}
skb = dev_alloc_skb(size+2);
if (skb == NULL) {
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
dev->name, size);
return;
}
/* Иначе*/
skb->dev = dev;
skb_reserve(skb,2); /* Align */
/* 'skb->data' указывет на начало буфера данных. */
buffer = skb_put(skb,size);
/* копируем пакет в буфер */
de600_setup_address(read_from, RW_ADDR);
for (i = size; i > 0; --i, ++buffer)
*buffer = de600_read_byte(READ_DATA, dev);
/* Определяем тип протокола
skb->protocol=eth_type_trans(skb,dev);
/*Передаем на верхний уровень см net/core/dev.c
netif_rx(skb);
/* обновляем статистику */
dev->last_rx = jiffies;
((struct net_device_stats *)(dev->priv))->rx_packets++; /* количество получений */
((struct net_device_stats *)(dev->priv))->rx_bytes += size; /* количество полученных байт */
/*
* Если случится что-то плохое во время доставки, netif_rx()
* сделало a mark_bh(INET_BH) для нас и будет работать
* когда мы войдем в bottom-halv.
*/
}
ip_finish_output() net/ipv4/ip_output
определяет девайс для данного маршрута
вызывает функцию девайса[=dev_queue_xmit]
ip_forward -net/ipv4/ip_forward
в этом файле хорошие комментарии
проверяем роутер
если пакет никому не предназначен то дропаем
если плохой TTL аналогично
если неможет пакет отфорвардится то отправляем icmp пакет ICMP_DEST_UNREACH
если необходимо шлем пакет ICMP HOST REDIRECT
копируем и уничтожаем старый пакет
уменьшаем TTL
если необходимо устанавливаем нужные опции ip_forward_options в
ip_forward_finish
ip_rcv net/ipv4/ip_input.c главная функция получения ip пакета
проверяем ошибки
плохая длина
версия
чексумма
вызываем pskb_trim
вызываем ip_route_input
Процесс маршрутизации
Как уже говорилось есть тоюлица соседей, FIB,routing cache Таблица соседей содержит адреса(mac) компьютеров которые физически соединены с нами. Linux использует АRP для определения адресов ета таблица динамическая хотя администраторы могут задать статические записи. Стуктуры связанные с етой таблицей описаны в include/net/neighbour.h основные структуры. struct neigh_table -их целый связаный список struct neigh_parms -список содержит разнообразную статистику struct neighbour -hash таблица соседей ассоциированных с данной таблицей struct pneig_entry -hash всех девайсов
поля struct neighbour
struct net_device -девайс
hh_cache -указатель на аппаратный кэш
sk_buff_head arp_queuq -очередь arp пакетов
есть local -в ней находятся свои интерфейсы
и main в ней наверное всё остальное
Forwarding Information Database
struct fib_table в include/net/ip_fib.h
содержит указатели на различные функции
tb_stamp
tb_id -255 для local и 254 для main
td_data -hash fib таблица
struct fn_hash -net/ipv4/fib_hash.c
struct fn_zone *fn_zones[33] -указатели на зоны
struct fn_zone *fn_zone_list указатель на первую не пустую зону
struct fn_zone содержит информацию про зону и маршруты для неё
struct fib_node ** fz_hash -указывает на кэш записей этой зоны
int fz_nent количество записей
int fx_divisor числу бакетов для зоны (в основном 16 кроме зоны 0000
loopback девайса)
int fz_order индекс зоны в родительской fn_hash
struct fib_node -содержит информацию по девайсу в fib_info(include/net/ip_fib.h)
метрику ,протокол и т.д
Routing Cache
Это наиболее быстрый способ нахождения маршрута Когда ip нужен маршрут ,то он определяет ячейку в хэше,которая указывает на цепочку маршрутов и идёт по этой цепочке пока не найдет нужный маршруты имеют таймеры и частоту использования ,наиболее частые перемещаются в начало.
struct rtable -звено в цепочке
содержит адреса отправителя и получателя
входящий интерфейс
адрес соседа или шлюза
struct dst_entry
содержит спецефические для данного маршрута данные и функции
struct dev -понятно
pmtu максимальная длина пакета для данного маршрута
int (*input)(struct sk_buff) -указатель на функцию приема для данного маршрута
часто ето tcp_rcv
int (*output)(struct sk_buff) указатель на функцию отсылки (dev_queue_xmit)
также разнообразные статистические данные и опции
Таким образом нами было проведено исследование сетевой архитектуры операционной системы Линух на примере реализации стека протоколов tcp-ip версии 4 в ядре 2.4.7
Приложение
После длительных теоретических изысканий применим их на практике
Нашей целью будет создание удобного пользовательского интерфейса для указания в пакете подставного ip адреса(адреса которого нет у никакого нашего интерфейса) Я не буду показывать ,то как адреса выставляются в ядре. Замечу только то что, из сокета семейства AF_INET и типа SOCK_RAW пакет с не своим адресом отправить вроде бы можно (в ядре 2.2 ,насчет 2.4 неуверен -может там есть какие-то проверки). страницы мана говорят про опцию IP_HDRINCL .Их можно отправлять также через тип SOCK_PACKET. Но для всего этого знать код ядра не очень необходимо. Поэтому мы пойдём други путём.
Наиболее легкий путь(?) сделать это через интерфейс setsockopt. После внимательного изучения кода функции sys_setsockopt -net/socket.c находим строки if ((sock = sockfd_lookup(fd, &err))!=NULL)
{
if (level == SOL_SOCKET)
err=sock_setsockopt(sock,level,optname,optval,optlen);
else
err=sock->ops->setsockopt(sock, level, optname, optval,optlen);
sockfd_put(sock);
}
return err;
}
значит нам надо искать функцию setsockopt в коде для реализации для типа sock_raw это файл net/ipv4/raw.c смотрим static int raw_setsockopt(struct sock *sk, int level, int optname,
char *optval, int optlen)
{
if (level != SOL_RAW)
return ip_setsockopt(sk, level, optname, optval, optlen);
...................................
}
функция ip_setsockopt лежит в net/ipv4/ip_sockglue.c в ней идет длинный перебор опций мы остановим свой выбор на уровне SOL_IP и добавим в перебор свои строки /*HACK:>>>>>>>>>>>>>>>*/
#ifdef CONFIG_HACKIP
case IP_HACKIP:
printk("HACKIP:setsockopt flag %d\n",sk->hackflag);
sk->hackflag=1;
get_user(val,(int *) optval);
printk("HACKIP:setsockopt val %d\n",val);
sk->hackf.src_addr=val;
break;
#endif
case IP_HDRINCL:
подробнее опишем происходящие действия
printk -выводим отлабочные сообщения
Я не уверен ,но судя по всему при создании сокета вся структура обнуляется поэтому мы можем не смотреть флаг .Я добавил эту строку ,чтоб посмотреть всегда ли он равен 0 при не установленной опции а после установки при повторе он равен 1. get_user забираем значение ,подробности include/asm/uaccess.h но для всего этого нам надо добавить соответствующие поля в struct sock =======sock.h=============
.........................
#ifdef CONFIG_HACKIP
/*HACK:>>>>>>>>>>>>>>>>>>*/
struct ip_hack {
__u32 src_addr;
};
#endif
struct sock {
/* Socket demultiplex comparisons on incoming packets. */
.................................
#ifdef CONFIG_HACKIP
/*HACK:>>>>>>>>>>>>>>>>>*/
struct ip_hack hackf;
int hackflag;
#endif
........................................
===========end======================
теперь нам надо перехватить отправку пакета
идем в файл net/ipv4/ip_output.c и после всех строк где есть 'iph->saddr=' вставляем наш код #ifdef CONFIG_HACKIP
if((sk->hackf.src_addr!=0)&&(sk->hackflag==1))
{
iph->saddr=sk->hackf.src_addr;
printk("HACKIP:ip_build_and_send.. %d\n",iph->saddr);
}
#endif
Осталось малое: в файл include/linux/in.h добавляем строку #define IP_HACKIP 16
в файл net/Config.in
bool 'HACKIP facilities' CONFIG_HACKIP делаем
cd /usr/src/linux
make menuconfig
make dep
make bzImage
cp arh/i386/boot/bzImage /boot/kursach
правим lilo.conf или /boot/grub/menu.lst
соответствуюшая команда
reboot....
теперь протестируем нашу программу извиняюсь за возможное наличие лишних include просто я переделал файл из друго-го проекта
============rel.c========================
/* Written by Gleb Paharenko 2003 */
/*Посвящяется Кевину Митнику */
/*и прекрасной весне в мае 2003-го*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define IP_HACKIP 16
int main()
{
int sd,res;
int value=1;
int sval=0;
int oval=1;
char buffer[100];
struct sockaddr_in addr,raddr;
bzero(buffer,sizeof(buffer));
if((sd=socket(PF_INET,SOCK_RAW,6))<0)
{
perror("Socket");
exit(errno);
}
bzero(&addr,sizeof(addr));
addr.sin_family=AF_INET;
raddr.sin_family=AF_INET;
addr.sin_port=0;
raddr.sin_port=0;
inet_aton("212.168.1.11",(struct sockaddr *)&(addr.sin_addr));
inet_aton("192.168.1.1",(struct sockaddr *)&(raddr.sin_addr));
sval=addr.sin_addr.s_addr;
inet_aton("192.168.1.10",(struct sockaddr *)&(addr.sin_addr));
if(bind(sd,(struct sockaddr *)&addr,sizeof(addr))<0)
{
perror("bind");
exit(errno);
}
if(connect(sd,(struct sockaddr *)&raddr,sizeof(raddr))!=0){
perror("connect");exit(errno);}
/* Вот ОНО!*/
if(setsockopt(sd,SOL_IP,IP_HACKIP,&sval,4)!=0)
{ perror("setsockopt");
exit(errno);
}
send(sd,"Kursovaja",10,0);
}
делаем
# gcc rel.c
#./a.out
#tail /var/log/messages
..................
..................
May 20 00:53:49 kursach -- root[863]: ROOT LOGIN ON tty1
May 20 00:53:51 kursach kernel: HACKIP:setsockopt flag 0
May 20 00:53:51 kursach kernel: HACKIP:setsockopt val 184658132
May 20 00:53:51 kursach kernel: HACKIP:ip_build_and_send.. 184658132
Обьясняю
дома у меня стоит vmware :host-only networking
host machine Windows2000 Professional 192.168.1.1/24
virtual Linux Red-Hat 7.2 "Enigma" 192.168.1.10/24
на 2000 запущен SpyNet
Ловим пакет и...
Работает!!!!!
Список литературы
Для подготовки данной работы были использованы материалы с сайта http://www.winsov.ru
0>0>