This source file includes following definitions.
- print_udp
- udp_select
- udp_err
- udp_check
- udp_send_check
- udp_send
- udp_sendto
- udp_write
- udp_ioctl
- udp_recvfrom
- udp_read
- udp_connect
- udp_close
- udp_rcv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <asm/system.h>
19 #include <asm/segment.h>
20 #include <linux/types.h>
21 #include <linux/sched.h>
22 #include <linux/fcntl.h>
23 #include <linux/socket.h>
24 #include <linux/sockios.h>
25 #include <linux/in.h>
26 #include <linux/errno.h>
27 #include <linux/timer.h>
28 #include <linux/termios.h>
29 #include <linux/mm.h>
30 #include "inet.h"
31 #include "dev.h"
32 #include "ip.h"
33 #include "protocol.h"
34 #include "tcp.h"
35 #include "skbuff.h"
36 #include "sock.h"
37 #include "udp.h"
38 #include "icmp.h"
39
40
41 #define min(a,b) ((a)<(b)?(a):(b))
42
43
44 static void
45 print_udp(struct udphdr *uh)
46 {
47 if (inet_debug != DBG_UDP) return;
48
49 if (uh == NULL) {
50 printk("(NULL)\n");
51 return;
52 }
53 printk("UDP: source = %d, dest = %d\n", ntohs(uh->source), ntohs(uh->dest));
54 printk(" len = %d, check = %d\n", ntohs(uh->len), ntohs(uh->check));
55 }
56
57
58 int
59 udp_select(struct sock *sk, int sel_type, select_table *wait)
60 {
61 select_wait(sk->sleep, wait);
62 switch(sel_type) {
63 case SEL_IN:
64 if (sk->rqueue != NULL) {
65 return(1);
66 }
67 return(0);
68
69 case SEL_OUT:
70 if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE) {
71 return(1);
72 }
73 return(0);
74
75 case SEL_EX:
76 if (sk->err) return(1);
77 return(0);
78 }
79 return(0);
80 }
81
82
83
84
85
86
87
88
89
90
91 void
92 udp_err(int err, unsigned char *header, unsigned long daddr,
93 unsigned long saddr, struct inet_protocol *protocol)
94 {
95 struct udphdr *th;
96 struct sock *sk;
97
98 DPRINTF((DBG_UDP,
99 "UDP: err(err=%d, header=%X, daddr=%X, saddr=%X, protocl=%X)\n",
100 err, header, daddr, saddr, protocol));
101
102 th = (struct udphdr *)header;
103 sk = get_sock(&udp_prot, th->dest, saddr, th->source, daddr);
104
105 if (sk == NULL) return;
106 if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8)) {
107 if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
108 return;
109 }
110
111 sk->err = icmp_err_convert[err & 0xff].errno;
112
113
114 if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) {
115 sk->prot->close(sk, 0);
116 }
117 }
118
119
120 static unsigned short
121 udp_check(struct udphdr *uh, int len,
122 unsigned long saddr, unsigned long daddr)
123 {
124 unsigned long sum;
125
126 DPRINTF((DBG_UDP, "UDP: check(uh=%X, len = %d, saddr = %X, daddr = %X)\n",
127 uh, len, saddr, daddr));
128
129 print_udp(uh);
130
131 __asm__("\t addl %%ecx,%%ebx\n"
132 "\t adcl %%edx,%%ebx\n"
133 "\t adcl $0, %%ebx\n"
134 : "=b"(sum)
135 : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
136 : "cx","bx","dx" );
137
138 if (len > 3) {
139 __asm__("\tclc\n"
140 "1:\n"
141 "\t lodsl\n"
142 "\t adcl %%eax, %%ebx\n"
143 "\t loop 1b\n"
144 "\t adcl $0, %%ebx\n"
145 : "=b"(sum) , "=S"(uh)
146 : "0"(sum), "c"(len/4) ,"1"(uh)
147 : "ax", "cx", "bx", "si" );
148 }
149
150
151 __asm__("\t movl %%ebx, %%ecx\n"
152 "\t shrl $16,%%ecx\n"
153 "\t addw %%cx, %%bx\n"
154 "\t adcw $0, %%bx\n"
155 : "=b"(sum)
156 : "0"(sum)
157 : "bx", "cx");
158
159
160 if ((len & 2) != 0) {
161 __asm__("\t lodsw\n"
162 "\t addw %%ax,%%bx\n"
163 "\t adcw $0, %%bx\n"
164 : "=b"(sum), "=S"(uh)
165 : "0"(sum) ,"1"(uh)
166 : "si", "ax", "bx");
167 }
168
169
170 if ((len & 1) != 0) {
171 __asm__("\t lodsb\n"
172 "\t movb $0,%%ah\n"
173 "\t addw %%ax,%%bx\n"
174 "\t adcw $0, %%bx\n"
175 : "=b"(sum)
176 : "0"(sum) ,"S"(uh)
177 : "si", "ax", "bx");
178 }
179
180
181 return((~sum) & 0xffff);
182 }
183
184
185 static void
186 udp_send_check(struct udphdr *uh, unsigned long saddr,
187 unsigned long daddr, int len, struct sock *sk)
188 {
189 uh->check = 0;
190 if (sk && sk->no_check) return;
191 uh->check = udp_check(uh, len, saddr, daddr);
192 }
193
194
195 static int
196 udp_send(struct sock *sk, struct sockaddr_in *sin,
197 unsigned char *from, int len)
198 {
199 struct sk_buff *skb;
200 struct device *dev;
201 struct udphdr *uh;
202 unsigned char *buff;
203 unsigned long saddr;
204 int size, tmp;
205 int err;
206
207 DPRINTF((DBG_UDP, "UDP: send(dst=%s:%d buff=%X len=%d)\n",
208 in_ntoa(sin->sin_addr.s_addr), ntohs(sin->sin_port),
209 from, len));
210
211
212 size = sizeof(struct sk_buff) + sk->prot->max_header + len;
213 skb = (struct sk_buff *) sk->prot->wmalloc(sk, size, 0, GFP_KERNEL);
214 if (skb == NULL) return(-ENOMEM);
215
216 skb->lock = 0;
217 skb->mem_addr = skb;
218 skb->mem_len = size;
219 skb->sk = NULL;
220 skb->free = 1;
221 skb->arp = 0;
222
223
224 buff = (unsigned char *) (skb+1);
225 saddr = 0;
226 dev = NULL;
227 DPRINTF((DBG_UDP, "UDP: >> IP_Header: %X -> %X dev=%X prot=%X len=%d\n",
228 saddr, sin->sin_addr.s_addr, dev, IPPROTO_UDP, skb->mem_len));
229 tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
230 &dev, IPPROTO_UDP, sk->opt, skb->mem_len);
231 if (tmp < 0 ) {
232 sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
233 return(tmp);
234 }
235 buff += tmp;
236 saddr = dev->pa_addr;
237 DPRINTF((DBG_UDP, "UDP: >> MAC+IP len=%d\n", tmp));
238
239 skb->len = tmp + sizeof(struct udphdr) + len;
240 skb->dev = dev;
241
242
243
244
245
246
247 if (len > dev->mtu) {
248 printk("UDP: send: length %d > mtu %d (ignored)\n", len, dev->mtu);
249 sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
250 return(-EINVAL);
251 }
252
253
254 uh = (struct udphdr *) buff;
255 uh->len = htons(len + sizeof(struct udphdr));
256 uh->source = sk->dummy_th.source;
257 uh->dest = sin->sin_port;
258 buff = (unsigned char *) (uh + 1);
259
260
261 err=verify_area(VERIFY_READ, from, len);
262 if(err)
263 return(err);
264 memcpy_fromfs(buff, from, len);
265
266
267 udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
268
269
270 sk->prot->queue_xmit(sk, dev, skb, 1);
271
272 return(len);
273 }
274
275
276 static int
277 udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
278 unsigned flags, struct sockaddr_in *usin, int addr_len)
279 {
280 struct sockaddr_in sin;
281 int tmp;
282 int err;
283
284 DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags));
285
286
287 if (flags) return(-EINVAL);
288 if (len < 0) return(-EINVAL);
289 if (len == 0) return(0);
290
291
292 if (usin) {
293 if (addr_len < sizeof(sin)) return(-EINVAL);
294 err=verify_area(VERIFY_READ, usin, sizeof(sin));
295 if(err)
296 return err;
297 memcpy_fromfs(&sin, usin, sizeof(sin));
298 if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL);
299 if (sin.sin_port == 0) return(-EINVAL);
300 } else {
301 if (sk->state != TCP_ESTABLISHED) return(-EINVAL);
302 sin.sin_family = AF_INET;
303 sin.sin_port = sk->dummy_th.dest;
304 sin.sin_addr.s_addr = sk->daddr;
305 }
306 sk->inuse = 1;
307
308
309 tmp = udp_send(sk, &sin, from, len);
310
311
312 release_sock(sk);
313 return(tmp);
314 }
315
316
317 static int
318 udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
319 unsigned flags)
320 {
321 return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
322 }
323
324
325 int
326 udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
327 {
328 int err;
329 switch(cmd) {
330 case DDIOCSDBG:
331 {
332 int val;
333
334 if (!suser()) return(-EPERM);
335 err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
336 if(err)
337 return err;
338 val = get_fs_long((int *)arg);
339 switch(val) {
340 case 0:
341 inet_debug = 0;
342 break;
343 case 1:
344 inet_debug = DBG_UDP;
345 break;
346 default:
347 return(-EINVAL);
348 }
349 }
350 break;
351 case TIOCOUTQ:
352 {
353 unsigned long amount;
354
355 if (sk->state == TCP_LISTEN) return(-EINVAL);
356 amount = sk->prot->wspace(sk)/2;
357 err=verify_area(VERIFY_WRITE,(void *)arg,
358 sizeof(unsigned long));
359 if(err)
360 return(err);
361 put_fs_long(amount,(unsigned long *)arg);
362 return(0);
363 }
364
365 case TIOCINQ:
366 #if 0
367 case FIONREAD:
368 #endif
369 {
370 struct sk_buff *skb;
371 unsigned long amount;
372
373 if (sk->state == TCP_LISTEN) return(-EINVAL);
374 amount = 0;
375 skb = sk->rqueue;
376 if (skb != NULL) {
377
378
379
380
381
382 amount = skb->len;
383 }
384 err=verify_area(VERIFY_WRITE,(void *)arg,
385 sizeof(unsigned long));
386 if(err)
387 return(err);
388 put_fs_long(amount,(unsigned long *)arg);
389 return(0);
390 }
391
392 default:
393 return(-EINVAL);
394 }
395 return(0);
396 }
397
398
399
400
401
402
403 int
404 udp_recvfrom(struct sock *sk, unsigned char *to, int len,
405 int noblock, unsigned flags, struct sockaddr_in *sin,
406 int *addr_len)
407 {
408 int copied = 0;
409 struct sk_buff *skb;
410 int er;
411
412 if (len == 0) return(0);
413 if (len < 0) return(-EINVAL);
414
415
416
417
418
419 if (sk->err) {
420 int err;
421
422 err = -sk->err;
423 sk->err = 0;
424 return(err);
425 }
426 if (addr_len) {
427 er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
428 if(er)
429 return(er);
430 put_fs_long(sizeof(*sin), addr_len);
431 }
432 if(sin)
433 {
434 er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
435 if(er)
436 return(er);
437 }
438 er=verify_area(VERIFY_WRITE,to,len);
439 if(er)
440 return er;
441 sk->inuse = 1;
442 while(sk->rqueue == NULL) {
443 if (sk->shutdown & RCV_SHUTDOWN) {
444 return(0);
445 }
446
447 if (noblock) {
448 release_sock(sk);
449 return(-EAGAIN);
450 }
451 release_sock(sk);
452 cli();
453 if (sk->rqueue == NULL) {
454 interruptible_sleep_on(sk->sleep);
455 if (current->signal & ~current->blocked) {
456 return(-ERESTARTSYS);
457 }
458 }
459 sk->inuse = 1;
460 sti();
461 }
462 skb = sk->rqueue;
463
464 if (!(flags & MSG_PEEK)) {
465 if (skb->next == skb) {
466 sk->rqueue = NULL;
467 } else {
468 sk->rqueue =(struct sk_buff *)sk->rqueue ->next;
469 skb->prev->next = skb->next;
470 skb->next->prev = skb->prev;
471 }
472 }
473 copied = min(len, skb->len);
474
475
476
477 memcpy_tofs(to, skb->h.raw + sizeof(struct udphdr), copied);
478
479
480 if (sin) {
481 struct sockaddr_in addr;
482
483 addr.sin_family = AF_INET;
484 addr.sin_port = skb->h.uh->source;
485 addr.sin_addr.s_addr = skb->daddr;
486
487
488
489
490 memcpy_tofs(sin, &addr, sizeof(*sin));
491 }
492
493 if (!(flags & MSG_PEEK)) {
494 kfree_skb(skb, FREE_READ);
495 }
496 release_sock(sk);
497 return(copied);
498 }
499
500
501 int
502 udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
503 unsigned flags)
504 {
505 return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
506 }
507
508
509 int
510 udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
511 {
512 struct sockaddr_in sin;
513 int er;
514
515 if (addr_len < sizeof(sin)) return(-EINVAL);
516
517 er=verify_area(VERIFY_READ, usin, sizeof(sin));
518 if(er)
519 return er;
520
521 memcpy_fromfs(&sin, usin, sizeof(sin));
522 if (sin.sin_family && sin.sin_family != AF_INET) return(-EAFNOSUPPORT);
523 sk->daddr = sin.sin_addr.s_addr;
524 sk->dummy_th.dest = sin.sin_port;
525 sk->state = TCP_ESTABLISHED;
526 return(0);
527 }
528
529
530 static void
531 udp_close(struct sock *sk, int timeout)
532 {
533 sk->inuse = 1;
534 sk->state = TCP_CLOSE;
535 if (sk->dead) destroy_sock(sk);
536 else release_sock(sk);
537 }
538
539
540
541 int
542 udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
543 unsigned long daddr, unsigned short len,
544 unsigned long saddr, int redo, struct inet_protocol *protocol)
545 {
546 struct sock *sk;
547 struct udphdr *uh;
548
549 uh = (struct udphdr *) skb->h.uh;
550 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
551 if (sk == NULL) {
552 if (chk_addr(daddr) == IS_MYADDR)
553 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
554
555
556
557
558
559
560 skb->sk = NULL;
561 kfree_skb(skb, FREE_WRITE);
562 return(0);
563 }
564
565 if (!redo) {
566 if (uh->check && udp_check(uh, len, saddr, daddr)) {
567 DPRINTF((DBG_UDP, "UDP: bad checksum\n"));
568 skb->sk = NULL;
569 kfree_skb(skb, FREE_WRITE);
570 return(0);
571 }
572
573 skb->sk = sk;
574 skb->dev = dev;
575 skb->len = len;
576
577
578 skb->daddr = saddr;
579 skb->saddr = daddr;
580
581
582 cli();
583 if (sk->inuse) {
584 if (sk->back_log == NULL) {
585 sk->back_log = skb;
586 skb->next = skb;
587 skb->prev = skb;
588 } else {
589 skb->next = sk->back_log;
590 skb->prev = sk->back_log->prev;
591 skb->prev->next = skb;
592 skb->next->prev = skb;
593 }
594 sti();
595 return(0);
596 }
597 sk->inuse = 1;
598 sti();
599 }
600
601
602 if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX) {
603 skb->sk = NULL;
604 kfree_skb(skb, FREE_WRITE);
605 release_sock(sk);
606 return(0);
607 }
608 sk->rmem_alloc += skb->mem_len;
609
610
611 DPRINTF((DBG_UDP, "<< \n"));
612 print_udp(uh);
613
614
615 if (sk->rqueue == NULL) {
616 sk->rqueue = skb;
617 skb->next = skb;
618 skb->prev = skb;
619 } else {
620 skb->next = sk->rqueue;
621 skb->prev = sk->rqueue->prev;
622 skb->prev->next = skb;
623 skb->next->prev = skb;
624 }
625 skb->len = len - sizeof(*uh);
626
627 if (!sk->dead) wake_up(sk->sleep);
628
629 release_sock(sk);
630 return(0);
631 }
632
633
634 struct proto udp_prot = {
635 sock_wmalloc,
636 sock_rmalloc,
637 sock_wfree,
638 sock_rfree,
639 sock_rspace,
640 sock_wspace,
641 udp_close,
642 udp_read,
643 udp_write,
644 udp_sendto,
645 udp_recvfrom,
646 ip_build_header,
647 udp_connect,
648 NULL,
649 ip_queue_xmit,
650 ip_retransmit,
651 NULL,
652 NULL,
653 udp_rcv,
654 udp_select,
655 udp_ioctl,
656 NULL,
657 NULL,
658 128,
659 0,
660 {NULL,},
661 "UDP"
662 };