Шрифт:
3 void
4 open_output(void)
5 {
6 int on=1;
7 /*
8 * Для отправки IP-дейтаграмм нужен символьный сокет
9 * Для его создания нужны права привилегированного пользователя.
10 * Кроме того, необходимо указать параметр сокета IP_HDRINCL.
11 */
12 rawfd = Socket(dest->sa_family, SOCK_RAW, 0);
13 Setsockopt(rawfd, IPPROTO_IP, IP_HDRINCL, &on., sizeof(on));
14 }
Объявление дескриптора символьного сокета
2
Мы объявляем глобальную переменную, в которой будет храниться дескриптор символьного сокета. Создание сокета и установка IP_HDRINCL
7-13
Мы создаем символьный сокет и включаем параметр сокета IP_HDRINCL
. Это позволяет нам формировать IP-дейтаграммы целиком, включая заголовок IP. В листинге 29.10 показана наша функция
udp_write
, которая формирует заголовки IP и UDP, а затем записывает дейтаграмму в символьный сокет. Листинг 29.10. Функция udp_write: формирование заголовков UDP и IP и запись дейтаграммы IP в символьный сокет
//udpcksum/udpwrite.c
19 void
20 udp_write(char *buf, int userlen)
21 {
22 struct udpiphdr *ui;
23 struct ip *ip;
24 /* заполнение заголовка и вычисление контрольной суммы */
25 ip = (struct ip*)buf;
26 ui = (struct udpiphdr*)buf;
27 bzero(ui, sizeof(*ui));
28 /* добавляем 8 к длине псевдозаголовка */
29 ui->ui_len = htons((uint16_t)(sizeof(struct udphdr) + userlen));
30 /* добавление 28 к длине IP-дейтаграммы */
31 userlen += sizeof(struct udpiphdr);
32 ui->ui_pr = IPPROTO_UDP;
33 ui->ui_src.s_addr = ((struct sockaddr_in*)local)->sin_addr.s_addr;
34 ui->ui_dst.s_addr = ((struct sockaddr_in*)dest)->sin_addr.s_addr;
35 ui->ui_sport = ((struct sockaddr_in*)local)->sin_port;
36 ui->ui_dport = ((struct sockaddr_in*)dest)->sin_port;
37 ui->ui_ulen = ui->ui_len;
38 if (zerosum == 0) {
39 #if 1 /* заменить на if 0 для Solaris 2.x. x < 6 */
40 if ((ui->ui_sum = m_cksum((u_int16_t*)in, userlen)) == 0)
41 ui->ui_sum = 0xffff;
42 #else
43 ui->ui_sum = ui->ui_len;
44 #endif
45 }
46 /* заполнение оставшейся части IP-заголовка */
47 /* функция p_output вычисляет и сохраняет контрольную сумму IP */
48 ip->ip_v = IPVERSION;
49 ip->ip_hl = sizeof(struct ip) >> 2;
50 ip->ip_tos = 0;
51 #if defined(linux) || defined(__OpenBSD__)
52 ip->ip_len = htons(userlen); /* сетевой порядок байтов */
53 #else
54 ip->ip_len = userlen; /* порядок байтов узла */
55 #endif
56 ip->ip_id = 0; /* это пусть устанавливает уровень IP */
57 ip->ip_off = 0; /* смещение флагов, флаги MF и DF */
58 ip->ip_ttl = TTL_OUT;